From 3901201460ed3366e0413d7ccccf274553888d18 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jakub=20Krop=C3=A1=C4=8Dek?= <kropikuba@gmail.com>
Date: Mon, 18 Dec 2023 21:00:37 +0100
Subject: [PATCH] Initial commit

---
 .gitignore                                    |   1 +
 account/__init__.py                           |   0
 account/__pycache__/__init__.cpython-312.pyc  | Bin 0 -> 158 bytes
 account/__pycache__/admin.cpython-312.pyc     | Bin 0 -> 205 bytes
 account/__pycache__/apps.cpython-312.pyc      | Bin 0 -> 469 bytes
 account/__pycache__/models.cpython-312.pyc    | Bin 0 -> 202 bytes
 account/__pycache__/urls.cpython-312.pyc      | Bin 0 -> 743 bytes
 account/__pycache__/views.cpython-312.pyc     | Bin 0 -> 2094 bytes
 account/admin.py                              |   3 +
 account/apps.py                               |   6 +
 account/migrations/__init__.py                |   0
 .../__pycache__/__init__.cpython-312.pyc      | Bin 0 -> 172 bytes
 account/models.py                             |   3 +
 account/templates/account/login.html          |  20 ++
 account/templates/account/me.html             |  15 ++
 account/templates/account/register.html       |   5 +
 account/tests.py                              |   3 +
 account/urls.py                               |  12 ++
 account/views.py                              |  40 ++++
 db.sqlite3                                    | Bin 0 -> 131072 bytes
 facturio/__init__.py                          |   0
 facturio/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 162 bytes
 facturio/__pycache__/settings.cpython-312.pyc | Bin 0 -> 2820 bytes
 facturio/__pycache__/urls.cpython-312.pyc     | Bin 0 -> 1482 bytes
 facturio/__pycache__/wsgi.cpython-312.pyc     | Bin 0 -> 652 bytes
 facturio/asgi.py                              |  16 ++
 facturio/settings.py                          | 128 ++++++++++++
 facturio/urls.py                              |  34 ++++
 facturio/wsgi.py                              |  16 ++
 manage.py                                     |  22 ++
 poetry.lock                                   |  67 +++++++
 pyproject.toml                                |  16 ++
 templates/facturio/base.html                  |  53 +++++
 templates/facturio/invoice.html               | 189 ++++++++++++++++++
 34 files changed, 649 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 account/__init__.py
 create mode 100644 account/__pycache__/__init__.cpython-312.pyc
 create mode 100644 account/__pycache__/admin.cpython-312.pyc
 create mode 100644 account/__pycache__/apps.cpython-312.pyc
 create mode 100644 account/__pycache__/models.cpython-312.pyc
 create mode 100644 account/__pycache__/urls.cpython-312.pyc
 create mode 100644 account/__pycache__/views.cpython-312.pyc
 create mode 100644 account/admin.py
 create mode 100644 account/apps.py
 create mode 100644 account/migrations/__init__.py
 create mode 100644 account/migrations/__pycache__/__init__.cpython-312.pyc
 create mode 100644 account/models.py
 create mode 100644 account/templates/account/login.html
 create mode 100644 account/templates/account/me.html
 create mode 100644 account/templates/account/register.html
 create mode 100644 account/tests.py
 create mode 100644 account/urls.py
 create mode 100644 account/views.py
 create mode 100644 db.sqlite3
 create mode 100644 facturio/__init__.py
 create mode 100644 facturio/__pycache__/__init__.cpython-312.pyc
 create mode 100644 facturio/__pycache__/settings.cpython-312.pyc
 create mode 100644 facturio/__pycache__/urls.cpython-312.pyc
 create mode 100644 facturio/__pycache__/wsgi.cpython-312.pyc
 create mode 100644 facturio/asgi.py
 create mode 100644 facturio/settings.py
 create mode 100644 facturio/urls.py
 create mode 100644 facturio/wsgi.py
 create mode 100755 manage.py
 create mode 100644 poetry.lock
 create mode 100644 pyproject.toml
 create mode 100644 templates/facturio/base.html
 create mode 100644 templates/facturio/invoice.html

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9f11b75
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.idea/
diff --git a/account/__init__.py b/account/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/account/__pycache__/__init__.cpython-312.pyc b/account/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..4dc59183f14502018846314279713d77bb102a65
GIT binary patch
literal 158
zcmX@j%ge<81m5RsQ$h4&5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!venPX&rQ|OF3K;^
z4@xb_FU~B<FUm|U*7qtcE(uO9N=@{w)K5!HE-5X_%-2sWEy>W2kI&4@EQycTE2#X%
fVUwGmQks)$SHuc5jS+~8L5z>gjEsy$%s>_ZF4ZSl

literal 0
HcmV?d00001

diff --git a/account/__pycache__/admin.cpython-312.pyc b/account/__pycache__/admin.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c572795b665183ead3be3822fe484928142ea7de
GIT binary patch
literal 205
zcmX@j%ge<81m5RsQ|*EDV-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9eI8O~zZS
zi7C06d48HqxA;=B67$mY^^)`RN{TX*ikN{4Rx*4BsrzNCpOK%Ns-InyU!Wh9T999y
zS(0CrnOdyxRa#sUoLrQe=v%3umY7^pT9lcupO~DSUz%5<4>nq_pz;@oO>TZlX-=wL
Z5eLvTMj$Q*F+MOeGBVy{P$*&pasY18HDmw)

literal 0
HcmV?d00001

diff --git a/account/__pycache__/apps.cpython-312.pyc b/account/__pycache__/apps.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9afe1475a7911875e7ba328986cd965fa9bb3bec
GIT binary patch
literal 469
zcmXv~Jxjzu5S>kOdftbKoPvdjjgTg3Ee_#S6a}x)F3qxLH)k}-#!XVhLJ;l;h|T>5
z@u%2mcLc1g?1a<iDtD8(#mt+1Z)SJiYq#41dEU3~*^|tls`x*R8q9Vim;eQe0tk_V
z5NL1=R2u`;8G6wxoulQ3+4xe0iHfB`93Sw=^G9w)R}t04tS7+)7&wT6qfzAORCA16
zH;tk@a9y57Y1MwWNv}yX;ugKMLQYwbSo{8Hkfr>{X8|o1Nu?f|jiQNhL_&sf(ZX1Y
zvq0ev#<v*>YG#!(k7PlLi5!8wa)zO}XPBwa&HMHh51D-<cx<1um?wV9h0hZEG)vM8
zS1@vx+a7V#O!(ZcU$;pdCsv#bWm*{w36ic1W0-F2z8UM&cJJX(sGE`>ntIW$S5wVG
s*;uuA6e@+w63v_aYLz{)B1`39qTKt|5keoZ{j;E<wa1fRkg4qY17*m0EC2ui

literal 0
HcmV?d00001

diff --git a/account/__pycache__/models.cpython-312.pyc b/account/__pycache__/models.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0140df8fbc821e0aabc851310f8164a23a2e9a7e
GIT binary patch
literal 202
zcmX@j%ge<81m5RsQ!Rn?V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9eI8O~zYn
zx%nxnImLdOOt&~wvJ&&s^Yv1aikN|tD;Yk6)cms3&&bbB)z2=<FVGK4Eyyp<EXgm*
zOfA;;DlIMvPA*DK^sUrSOH3{)Ey~Q-PfSkEFU>2_hZw6@Q2C3)2FNbWNwq8D02;>#
U#Kj=S2WCb_#(NAhMQlJ00HTF7A^-pY

literal 0
HcmV?d00001

diff --git a/account/__pycache__/urls.cpython-312.pyc b/account/__pycache__/urls.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9152a610ca2d836f699670f3aeee4620d4486cc5
GIT binary patch
literal 743
zcmZ`$L2J}N6rLoLY<9ET*6zAgJV{+_E)57hSv)BeK@Sz7<g$d#xJgYiVKUL~9t3ae
z$@SF!go+;gAD$Khiv!|8JoHxSMSAkh))-iD4)1;6d*8hG=FOK@tAXI;z1JjA5c(lW
zdFp?`#cu$|$Va{sp;&PhMPfBlW6jlK>|)@Wk0U)cTth)BBATxg<8Y-cRC(X{RQsr1
z@rBO(kFLI?Yk+R8s#7B0TGBN^w_au|@3)q8E1>IC`4ai7m2RlJ)@aSXb|#ayBAR=g
zr~4#JX_66J6*%>HAZm>CB{+laNtOOGB(E}ogc=i|IPqdK)?(raBPM-vl#Y#v4#UI|
z`ofQE;AqYve+9;MMuuU=33G&5!Y6i9SpK1x4C!_NV=%eHf03L;8N(1^x-_OVHEHAz
ziiVf-pucD)tP(><(OQtQg|MIuyaXC2*#~q1SJCCJ6Hu7_1*566Pg0tNoU)K)&Z9iz
zPX~;6k4MgPZ@_aFQpXz%Xr6FK&a<74F3sJT`gug|vkfRF7nH?d&NW3*zM<RSQST>e
z|1ywXpR7-wy*qe&aPpwQx4vR?a(${FoA1q&qXKV9zA@dIw>M|)&C@#tzAGa)rVr<x
j-mKF*-7D~pjNF`(dDotG?az$@-#fRARrQU<y3p|tta`be

literal 0
HcmV?d00001

diff --git a/account/__pycache__/views.cpython-312.pyc b/account/__pycache__/views.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d10ca6a5da903204a48840d35e0f5ec18bd4607c
GIT binary patch
literal 2094
zcmbtV&2Jk;6rcU@=dSI<P8+EE5t>4?m9SG9sYL~PC~ea;Bvn2TGDu<ZPLoZ&yJ2SB
zk`PdlA`wow5-2&QCt4*(4*U;XoF-Dk%2kl)g_~)5>WMdFZ=6K*#7Leu@6CH}e(!7j
zdm<4>u*Uno#pw`2e{m*Qz>Br>5Xcg;kR_FnBNZfxpXHM5C<Vn)3#t<;goI2fg`G$t
zBF<_l>ck2$Ctip<T0s-CP)T<Zg@ltVB!Lg(m=(eCTdEaZPzxy>*&~T9sH@HA3vGMk
zanNkvr>X7HOwZ~@;%{zeNPd)J#%y<z8j7!*Wj2LfW*1F{{ZPr9v|T?8#49sUO$xyT
z!C#hbf-Nx6`Wc%U0UlH4>kWp^crL}hK0rNp1UEQC_M>0{Rz>EA33e?^d<7hFhLwq1
zl$v31!ZWJCZ|8H6E}?le&7}vHCEe~ph|I#ReBcULOMV^pZ=_e;D&kgVLG9p;d1+o=
zQ&;)B+)|lWXo^J|9QX@aVOz2yYthx_Yomz8f?Kdw0=a~k){;-_!MR1P7)u7+bX#z0
z(OnEG%LLMSb+wtH(O2aoF7lzXL%TM}(gIX~wlk1hIz+MS%}5OS>doQNF+W<Sn7F2c
z{pgHI>0OUlhD_SQjHF@nBMzq2oWygP>+T)1WLsTDC?3?(HcQmL4<4aM!jze;OnueG
zUol^~c4cfXZ5E4O*=2drKDjC8l<c3mw(f@=%%(hx@GKCOZ+y-OFN+_U#Ndh%a+r&F
zUHtUm@U`nh6C+nXygqW}^4P@q$ROd#COpf8m%|8=1V6V>t2`=S54vxnOiGmd@8av_
z`}rx)!TH<7o5_#h8IRh`BQ~b_fih*I5TE(cZ2p#6gdVlMd=SVT8{eh5nOQ&12WCRV
zMUH{fDE#OeZ1>PsB>w%}cXO4GA4jrVnZrvL?q66QSkIhZjPB=ZsqFIQhdsZ2vYEQN
zsQ!`4)G{aj>^N3E(N|aG_H;drUdz6Sg*uXT6iOstBvB$=>8`L%{b((Fa^>7F=O3JZ
zc=gx*Cw;@~eZw2sn~Q_BOm=y2BV$x`V=Jcrc;ts8mGa}*(OT+IrC818H&VUTXm3sH
zT&9~^cUA4)0laA60P<vu0UUtC5@O9}LC|_Z<3O7?M+G6qD<{@;I5@RvU@;2qF=VKO
zt2C-6YMOzX4v&xRE9xUjRFU#`yU0=4eJ#i|e2U0PknnWVBe2~=&(!$hxrG}wE%Q_V
zlaAi?j@}LJY*jr=j>Gl7z&KD57&qJ>m?gDl#gK>Q4h6*~c+#c}6VbSUO!V3tV80h$
zLcj}D$(wN9%~g0~-$OO6z0zIn%x!4-s+#{_uu=gm2Ma*t6udwV!jT<JPQ%4pEey{Z
z7<x7|qpBJL!;q2jHEY^*C%s(Jb8j_<EYp%OVt<k2ku_$MkBumwfBZjmauzOn#Dw{w
zgnu`8T~EP(1mTk*CR9wg-_~?Mr#!-nWk&bRF|VvBu}Gtc;}H^oMJv3FzUO#Wxr9F;
zInd-iLKk4GE0QEVMP1wI;ySwc6urBRF0G?W+vx3jI4zy3+^8cUD}y_n)XyNftuD*b
zJC#rC2*}E3&pFvq0(m_yNxhY?>j=oo{0=8Di`+<(&Mbm6Aj^Z#IT1$xaJfMFFTIr0
A`v3p{

literal 0
HcmV?d00001

diff --git a/account/admin.py b/account/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/account/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/account/apps.py b/account/apps.py
new file mode 100644
index 0000000..2c684a9
--- /dev/null
+++ b/account/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class AccountConfig(AppConfig):
+    default_auto_field = "django.db.models.BigAutoField"
+    name = "account"
diff --git a/account/migrations/__init__.py b/account/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/account/migrations/__pycache__/__init__.cpython-312.pyc b/account/migrations/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..415a57d1bbf13dba6b881357ee3bccf218367a18
GIT binary patch
literal 172
zcmX@j%ge<81m5RsQ$h4&5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!^48DD&rQ|OF3K;^
z4@xb_FU~B<FUm|U*7qtcE(uO9N=@{w)K5!HE-5X_%-2s$PR=jQE78x*OfO0-$;{6y
t){l?R%*!l^kJl@x{Ka9Do1apelWJGQ3N)J$h>JmtkIamWj77{q769<-Ee-$x

literal 0
HcmV?d00001

diff --git a/account/models.py b/account/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/account/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/account/templates/account/login.html b/account/templates/account/login.html
new file mode 100644
index 0000000..5fc5313
--- /dev/null
+++ b/account/templates/account/login.html
@@ -0,0 +1,20 @@
+{% extends "facturio/base.html" %}
+
+{% block title %}Login{% endblock %}
+
+{% block content %}
+    <div class="container mt-5">
+        <form class="col-md-6 offset-md-3" action="{% url 'login' %}" method="post">
+            {% csrf_token %}
+            <div class="mb-3">
+                <label for="username" class="form-label">Username</label>
+                <input type="text" class="form-control" name="username" id="username" required>
+            </div>
+            <div class="mb-3">
+                <label for="password" class="form-label">Password</label>
+                <input type="password" class="form-control" name="password" id="password" required>
+            </div>
+            <button type="submit" class="btn btn-primary">Login</button>
+        </form>
+    </div>
+{% endblock %}
diff --git a/account/templates/account/me.html b/account/templates/account/me.html
new file mode 100644
index 0000000..636e701
--- /dev/null
+++ b/account/templates/account/me.html
@@ -0,0 +1,15 @@
+{% 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">
+            <div class="card-body">
+                <h5 class="card-title">Welcome, {{ request.user.username }}!</h5>
+                <p class="card-text">Email: {{ request.user.email }}</p>
+            </div>
+        </div>
+    </div>
+{% endblock %}
diff --git a/account/templates/account/register.html b/account/templates/account/register.html
new file mode 100644
index 0000000..cd31cfa
--- /dev/null
+++ b/account/templates/account/register.html
@@ -0,0 +1,5 @@
+{% extends "facturio/base.html" %}
+{% block title %}Register{% endblock %}
+{% block content %}
+    <h1>TODO: register</h1>
+{% endblock %}
\ No newline at end of file
diff --git a/account/tests.py b/account/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/account/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/account/urls.py b/account/urls.py
new file mode 100644
index 0000000..2184e52
--- /dev/null
+++ b/account/urls.py
@@ -0,0 +1,12 @@
+from django.http import HttpResponse
+from django.urls import path, re_path
+
+from . import views
+
+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"),
+]
diff --git a/account/views.py b/account/views.py
new file mode 100644
index 0000000..6e1a9c4
--- /dev/null
+++ b/account/views.py
@@ -0,0 +1,40 @@
+from django.conf import settings
+from django.contrib.auth import authenticate, login, logout
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest, HttpResponse, JsonResponse
+from django.shortcuts import redirect, render
+
+
+def auth_login(req: HttpRequest) -> HttpResponse:
+    if req.method == "POST":
+        username = req.POST["username"]
+        password = req.POST["password"]
+        user = authenticate(req, username=username, password=password)
+        if not user:
+            return JsonResponse(
+                {
+                    "message": "Invalid cretendials"
+                },
+                status=401
+            )
+        else:
+            login(req, user)
+            redirect_url = getattr(req.GET, "next", settings.LOGIN_REDIRECT_URL)
+            return redirect(redirect_url)
+    elif req.method == "GET":
+        return render(req, "account/login.html")
+    return HttpResponse(status=405)
+
+
+@login_required
+def auth_logout(req: HttpRequest) -> HttpResponse:
+    logout(req)
+    return redirect(settings.LOGOUT_REDIRECT_URL)
+
+
+def auth_register(req: HttpRequest) -> HttpResponse:
+    return render(req, "account/register.html")
+
+@login_required
+def me(req: HttpRequest) -> HttpResponse:
+    return render(req, "account/me.html")
diff --git a/db.sqlite3 b/db.sqlite3
new file mode 100644
index 0000000000000000000000000000000000000000..ce718fefd44d1b34fa0dc746287201f90f2b3682
GIT binary patch
literal 131072
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
DDisfP

literal 0
HcmV?d00001

diff --git a/facturio/__init__.py b/facturio/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/facturio/__pycache__/__init__.cpython-312.pyc b/facturio/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..a6b7f860aec0eb079ab2011d51c64ee601011a7d
GIT binary patch
literal 162
zcmX@j%ge<81bbK2rh@3lAOanHW&w&!XQ*V*Wb|9fP{ah}eFmxd<*1*LpPQ<mU6fy-
zACy{<Uz}NzUzC|ztnXD?ToRmIl$z*Ush^gZTvA$;nU7$^$7kkcmc+;F6;%G>u*uC&
bDa}c>D`Ewj$Oy#6AjU^#Mn=XWW*`dyA(kms

literal 0
HcmV?d00001

diff --git a/facturio/__pycache__/settings.cpython-312.pyc b/facturio/__pycache__/settings.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..3e2e0ceb91312a547f0186257c8ea65cd3371281
GIT binary patch
literal 2820
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
Wtn`!7>iR#d(WQ-3s$gzHJ^v3N*Qlrf

literal 0
HcmV?d00001

diff --git a/facturio/__pycache__/urls.cpython-312.pyc b/facturio/__pycache__/urls.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f2edb07ca84c58a51af9ec44e5989e56abae366b
GIT binary patch
literal 1482
zcmb7EPjB2r6d!wM|Jg}4tyIyL%RoRIONreg^|GQ=2vM~NdPs|q_Ry_k&+a<4J?_l7
zG^>h&#39G#lzfFMd<4D$mrCIP7Kj4}#4T0Cr6=C=+R+LL34C~d@6DUvy!U(a=7;5F
zi@^8O+h1{)67oA5_1CVH)9*n!AR!r&&<M@gNX(&Wpx%fZ2_4d;Ic%0Tjax~3*e>;E
z+)28_Zek5Buv?slZQdNyu=6b)+9u)Mu*>bx`p!OT%+D!(OCYUq`N)|2j?9I%6>jca
zoZE|X=klU8*Xw<g#&Bh~=dAkA0Lc1$>r)npbR11`>FY?OY%C-j`+?47Bv>ZJ4iB_z
zS@))#J;-I8`C4<Css}8Nlx9-onkxn{ifO?fNBm3WvYUXB2+3KL0$ef&&SLH>&J^bZ
zi@`V5I#UDB3q_#ZaK}$4qCPGViN{m#ntR35B8vj$VXz0sE6@7)iJt(L8dx{;G$?Z}
zk1av3y6nR+WPZw`Bok5(7#mBGuw-}SXIbT(r&-3oSH)umSinMsuoa4(uJ`*JRb5k&
z@C}yw3BTS)z3*5b#lBLT+fZ1zfckG)2tDNz6LHIo>vV1b*8j-{<6U2k5M<r?M@F~P
zAkM=mod5~tc~}~@xaQ|}NeqKjpgkDN*Bv&ls2t4cnzzG6!s{ff*o~5u|D5f1EG8Zh
zSfA8KM~T~a9P3ZKnvPL4{V<7A$1Lny(C01wDCbHSOLIeIB31l_QM4paLoOkVVq=PS
z1zI#De}t=WXVah>lk(ET_!1nYQ=EqbqR-Zz!l>2*ahEveo!N!@&U;b%SVRGLr#gvc
z3pP52#1}!~Zua`RhpqP>N|AY6JQFI?LPlJ9pX5s44J7wJ+x5=C&J?85&2|eKa+r)2
zfVza3t02B6zu4!Vuf2T3J+{4<)H?+qDafpw_))r<`4bKlQM`7ujvoXfPqjB&s<e{J
zS*s+_yW{kV_GknXH5wHwRTH82T1MLvi74#KiSs0p9@#|qYUNf_n3*8gO5#g*7LCcv
z4n}uTVD<%t!g)b)sjxxT55o&0dl<9~;&tc!M1*<FKag*Ni3BPi#7V<2j8|sQpnox9
zy!8jU`YT!cjl6r(F^nsF4^IgE4&zh&y|PHNyLW!?-l6>?edlM|*}J^|#o_(q3meCD
d6U~dyuN@5b2M0IyZyeLLlQ!*{-`Hgee*>X~ss;c6

literal 0
HcmV?d00001

diff --git a/facturio/__pycache__/wsgi.cpython-312.pyc b/facturio/__pycache__/wsgi.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ee5289ed690b72fc71367a6d6fef77724305b173
GIT binary patch
literal 652
zcmYjP!EO^V5VdzhQ*CGji1utDE|Fjz4qOl*AyT4LG?hpZQZ5^JJxLwB>y_=Kq!Ndo
z5MRJIK)-=6;8Fw<Xip%-fg32dp71tZrE~DS@#xKaWBJqCT7X=9{O}syVuXGbMH!WI
zFyC|F9pb2uIOd+jeeAL?y~OYP7y%xymXu{4*Os_MyuvRXdy5Jq4}pJt-s-Q+yvEAm
z_uxgZ-663`hhjvAN|Par?L-SjGOflC+b{?^mcXk_88F1|16eSblx$A|VTLf0C_a&J
zTf!71nKCWTS}99_lfi&xnG`XzLZyR&oA<=YBuWDjsZ&hO8bqaTxG-cWB-|nfAlSDy
zGxsRvDmEb>vvj0NPq9iUr1Wmsr2Fc?D#{^~YL-B1>46yu8vH5t>^5+IeFQct?xG7e
z@{QKkqi%aA>TT}scDn6ew7t`M{&e&3YPo)Bz*>=xOrx4tqsV!PqTEv^zp`)=#%_VI
zn5%uKlvg303a!#Sa6}G6Hjy^3U66c_=7pux2hMQ<^rcoAeFpATg;iRBp<5GUd$9(#
zJ)@<IB`B1_Y<9YOfAQ82b=^&K9|)PIJO26@<9}WiSLW9c4t}FMKalq(I10X@_0MSi
YWFtIjKK_bYKkGNX)NdZu^kql-4}<Z*^Z)<=

literal 0
HcmV?d00001

diff --git a/facturio/asgi.py b/facturio/asgi.py
new file mode 100644
index 0000000..e395568
--- /dev/null
+++ b/facturio/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for facturio project.
+
+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")
+
+application = get_asgi_application()
diff --git a/facturio/settings.py b/facturio/settings.py
new file mode 100644
index 0000000..b63d289
--- /dev/null
+++ b/facturio/settings.py
@@ -0,0 +1,128 @@
+"""
+Django settings for facturio project.
+
+Generated by 'django-admin startproject' using Django 5.0.
+
+For more information on this file, see
+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
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+# Quick-start development settings - unsuitable for production
+# 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"
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = ['*']
+
+# Application definition
+
+INSTALLED_APPS = [
+    "django.contrib.admin",
+    "django.contrib.auth",
+    "django.contrib.contenttypes",
+    "django.contrib.sessions",
+    "django.contrib.messages",
+    "django.contrib.staticfiles",
+    "account.apps.AccountConfig"
+]
+
+MIDDLEWARE = [
+    "django.middleware.security.SecurityMiddleware",
+    "django.contrib.sessions.middleware.SessionMiddleware",
+    "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"
+
+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",
+            ],
+        },
+    },
+]
+
+STATICFILES_DIRS = [
+    BASE_DIR / "static",
+]
+
+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",
+    }
+}
+
+# Password validation
+# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
+    },
+    {
+        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
+    },
+    {
+        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
+    },
+    {
+        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
+    },
+]
+
+# Internationalization
+# https://docs.djangoproject.com/en/5.0/topics/i18n/
+
+LANGUAGE_CODE = "en-us"
+
+TIME_ZONE = "UTC"
+
+USE_I18N = True
+
+USE_TZ = True
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/5.0/howto/static-files/
+
+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"
+
+# Login configuration
+LOGIN_BASE_URL = "/account"
+LOGIN_URL = f"{LOGIN_BASE_URL}/login"
+LOGOUT_REDIRECT_URL = f"/"
+LOGIN_REDIRECT_URL = f"{LOGIN_BASE_URL}/me"
diff --git a/facturio/urls.py b/facturio/urls.py
new file mode 100644
index 0000000..5f34c30
--- /dev/null
+++ b/facturio/urls.py
@@ -0,0 +1,34 @@
+"""
+URL configuration for facturio project.
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/5.0/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+# TODO: remove
+from django.http import HttpRequest, HttpResponse
+from django.shortcuts import render
+from django.urls import path, include
+
+
+# TODO: remove
+def demo(req: HttpRequest) -> HttpResponse:
+    return render(req, "facturio/invoice.html")
+
+
+urlpatterns = [
+    path("", demo, name="main-page"),
+    path("account/", include("account.urls")),
+    path("admin/", admin.site.urls),
+]
+
diff --git a/facturio/wsgi.py b/facturio/wsgi.py
new file mode 100644
index 0000000..57369aa
--- /dev/null
+++ b/facturio/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for facturio project.
+
+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")
+
+application = get_wsgi_application()
diff --git a/manage.py b/manage.py
new file mode 100755
index 0000000..3e35f11
--- /dev/null
+++ b/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+    """Run administrative tasks."""
+    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?"
+        ) from exc
+    execute_from_command_line(sys.argv)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 0000000..1b9573a
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,67 @@
+# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+
+[[package]]
+name = "asgiref"
+version = "3.7.2"
+description = "ASGI specs, helper code, and adapters"
+optional = false
+python-versions = ">=3.7"
+files = [
+    {file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
+    {file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
+]
+
+[package.extras]
+tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
+
+[[package]]
+name = "django"
+version = "5.0"
+description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
+optional = false
+python-versions = ">=3.10"
+files = [
+    {file = "Django-5.0-py3-none-any.whl", hash = "sha256:3a9fd52b8dbeae335ddf4a9dfa6c6a0853a1122f1fb071a8d5eca979f73a05c8"},
+    {file = "Django-5.0.tar.gz", hash = "sha256:7d29e14dfbc19cb6a95a4bd669edbde11f5d4c6a71fdaa42c2d40b6846e807f7"},
+]
+
+[package.dependencies]
+asgiref = ">=3.7.0"
+sqlparse = ">=0.3.1"
+tzdata = {version = "*", markers = "sys_platform == \"win32\""}
+
+[package.extras]
+argon2 = ["argon2-cffi (>=19.1.0)"]
+bcrypt = ["bcrypt"]
+
+[[package]]
+name = "sqlparse"
+version = "0.4.4"
+description = "A non-validating SQL parser."
+optional = false
+python-versions = ">=3.5"
+files = [
+    {file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
+    {file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
+]
+
+[package.extras]
+dev = ["build", "flake8"]
+doc = ["sphinx"]
+test = ["pytest", "pytest-cov"]
+
+[[package]]
+name = "tzdata"
+version = "2023.3"
+description = "Provider of IANA time zone data"
+optional = false
+python-versions = ">=2"
+files = [
+    {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
+    {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.12"
+content-hash = "1c6ab57fc89858a0923620d3307e9173662bad9b58d9dde4f567267506e03587"
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..9c01d30
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,16 @@
+[tool.poetry]
+name = "facturio"
+version = "0.1.0"
+description = ""
+authors = ["Jakub Kropáček <kropikuba@gmail.com>"]
+license = "MIT"
+readme = "README.md"
+
+[tool.poetry.dependencies]
+python = "^3.12"
+django = "^5.0"
+
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
diff --git a/templates/facturio/base.html b/templates/facturio/base.html
new file mode 100644
index 0000000..9615bd7
--- /dev/null
+++ b/templates/facturio/base.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html lang="cs">
+<head>
+    <meta charset="UTF-8">
+    <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">
+    <div class="container-fluid">
+        <a class="navbar-brand" href="#">Facturio</a>
+
+        <!-- Left-aligned items -->
+        <div class="collapse navbar-collapse" id="navbarLeft">
+            <ul class="navbar-nav">
+                <!-- Additional items on the left -->
+                <li class="nav-item">
+                    <a class="nav-link" href="#">Item 1</a>
+                </li>
+                <li class="nav-item">
+                    <a class="nav-link" href="#">Item 2</a>
+                </li>
+                <!-- Add more items as needed -->
+            </ul>
+        </div>
+
+        <!-- Right-aligned login/logout links -->
+        <div class="collapse navbar-collapse justify-content-end" id="navbarRight">
+            <ul class="navbar-nav">
+                {% if request.user.is_authenticated %}
+                    <li class="nav-item">
+                        <a class="nav-link" href="{% url 'logout' %}">Logout</a>
+                    </li>
+                {% else %}
+                    <li class="nav-item">
+                        <a class="nav-link" href="{% url 'login' %}">Login</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" href="{% url 'register' %}">Register</a>
+                    </li>
+                {% endif %}
+            </ul>
+        </div>
+    </div>
+</nav>
+
+<div class="container mt-4">
+    {% block content %} {% endblock %}
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/templates/facturio/invoice.html b/templates/facturio/invoice.html
new file mode 100644
index 0000000..12413f2
--- /dev/null
+++ b/templates/facturio/invoice.html
@@ -0,0 +1,189 @@
+<!-- Vaše faktura s aktualizacemi -->
+<!DOCTYPE html>
+<html lang="cs">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Faktura</title>
+    <style>
+        @import url("https://fonts.googleapis.com/css2?family=Ubuntu&display=swap");
+
+        :root {
+        --font-family: "Ubuntu", sans-serif;
+        --main-color: #333;
+        --secondary-color: #888;
+        --border-color: #ddd;
+        --background-color: #fff;
+      }
+
+        body {
+        font-family: var(--font-family);
+        margin: 20px;
+        color: var(--main-color);
+        background-color: var(--background-color);
+      }
+
+      header {
+        text-align: left;
+        margin-bottom: 20px;
+      }
+
+      .parties ul {
+        list-style-type: none;
+        padding: 0;
+        margin: 0;
+      }
+
+      .parties li {
+        margin-top: 5px;
+      }
+
+      .parties h2 {
+        border-bottom: 1px solid var(--border-color);
+        padding-bottom: 8px;
+        font-size: 1.2rem;
+      }
+
+      .invoice-id {
+        color: var(--secondary-color);
+      }
+
+      #invoice {
+        border-collapse: collapse;
+        width: 100%;
+      }
+
+      #invoice th,
+      #invoice td {
+        padding: 12px;
+        text-align: left;
+        border-bottom: 1px solid var(--border-color);
+      }
+
+      .invoice-total {
+        margin-top: 20px;
+        text-align: right;
+      }
+
+      .parties-section {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 20px;
+      }
+
+      .parties {
+        width: 48%;
+      }
+
+      #invoice tbody tr {
+        border-bottom: 1px solid var(--border-color);
+      }
+
+      .small-col {
+        width: 5%;
+      }
+      .medium-col {
+        width: 15%;
+      }
+      .big-col {
+        width: 25%;
+      }
+      .right-align {
+        text-align: right;
+      }
+
+      footer {
+        position: fixed;
+        bottom: 0;
+        width: 100%;
+        text-align: center;
+        left: 0;
+        right: 0;
+        padding: 0;
+        margin-top: 20px;
+        color: var(--main-color);
+        background-color: var(--background-color);
+      }
+
+      @media print {
+        @page {
+          size: auto;
+          margin: 0;
+        }
+
+        body {
+          margin: 10mm 10mm;
+        }
+      }
+    </style>
+  </head>
+  <body>
+    <header>
+      <h1>Faktura <span class="invoice-id">2023-0001</span></h1>
+    </header>
+
+    <section class="parties-section">
+      <div class="parties">
+        <h2>Dodavatel</h2>
+        <ul>
+          <li>Název Vaší společnosti nebo jméno</li>
+          <li>Vaše adresa</li>
+          <li>Vaše město, PSČ</li>
+          <p></p>
+          <li>IČO: 123456789</li>
+          <li>DIČ: CZ123456789 jestli jste plátce DPH</li>
+          <p></p>
+          <li>Bankovní účet: 123-456789</li>
+        </ul>
+      </div>
+
+      <div class="parties">
+        <h2>Odběratel</h2>
+        <ul>
+          <li>Název společnosti nebo jméno zákazníka</li>
+          <li>Adresa zákazníka</li>
+          <li>Město zákazníka, PSČ</li>
+          <p></p>
+          <li>IČO zákazníka: 987654321</li>
+          <li>DIČ zákazníka: CZ987654321 jestli je plátce DPH</li>
+          <p></p>
+          <li><strong>Datum vystavení:</strong> 16. prosince 2023</li>
+          <li><strong>Datum splatnosti:</strong> 16. prosince 2023</li>
+        </ul>
+      </div>
+    </section>
+
+    <section>
+      <h2>Detaily faktury</h2>
+      <table id="invoice">
+        <thead>
+          <tr>
+            <th class="small-col">#</th>
+            <th class="small-col">Jednotka</th>
+            <th class="big-col">Popis položky</th>
+            <th class="medium-col right-align">Cena za MJ</th>
+            <th class="medium-col right-align">Celkem</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr>
+            <td>1</td>
+            <td>ks</td>
+            <td>Položka 1</td>
+            <td class="right-align">50,00 Kč</td>
+            <td class="right-align">50,00 Kč</td>
+          </tr>
+        </tbody>
+      </table>
+
+      <div class="invoice-total">
+        <p><strong>Celkem: 100,00 Kč</strong></p>
+      </div>
+    </section>
+
+    <footer>
+      <p>Fyzická osoba zapsaná v živnostenském rejstříku.</p>
+      <p>Fakturu vygenerovala aplikace Facturio</p>
+    </footer>
+  </body>
+</html>