Implement basic invoicing
This commit is contained in:
parent
b21c828f2e
commit
681f85b1b8
54 changed files with 2709 additions and 232 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -158,3 +158,6 @@ cython_debug/
|
||||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# Drawio
|
||||||
|
.*.drawio.bkp
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
|
# See https://pre-commit.com for more information
|
||||||
|
# See https://pre-commit.com/hooks.html for more hooks
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v3.2.0
|
rev: v4.6.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- repo: https://github.com/asottile/reorder-python-imports
|
- repo: https://github.com/pre-commit/mirrors-autopep8
|
||||||
rev: v3.12.0
|
rev: v2.0.4
|
||||||
hooks:
|
hooks:
|
||||||
- id: reorder-python-imports
|
- id: autopep8
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/asottile/add-trailing-comma
|
||||||
rev: v0.2.0
|
rev: v3.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: add-trailing-comma
|
||||||
args: [ --fix, --exit-non-zero-on-fix ]
|
- repo: https://github.com/asottile/reorder-python-imports
|
||||||
- id: ruff-format
|
rev: v3.13.0
|
||||||
|
hooks:
|
||||||
|
- id: reorder-python-imports
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.5.5
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [--fix, --exit-non-zero-on-fix]
|
||||||
|
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Facturio
|
||||||
|
- DB Schema: [dbdiagram.io](https://dbdiagram.io/d/Facturio-65c15011ac844320ae80e86e) -- TODO: Update
|
||||||
|
- KanBoard: [board.katuwoss.dev](https://board.katuwoss.dev/public/board/b64e04ae8ba0cc2fa26712ccd555ea4e4290b8463a8ef6e3a19aa74829c4)
|
21
TODO.md
21
TODO.md
|
@ -1,21 +0,0 @@
|
||||||
# TODO
|
|
||||||
|
|
||||||
## Localisation
|
|
||||||
|
|
||||||
- [ ] It would be nice to centralize the translations to some well-chosen singular directory
|
|
||||||
- [ ] Integrate it with some public translation project?
|
|
||||||
|
|
||||||
## DevOps Functionality
|
|
||||||
- [ ] I need to dockerize it
|
|
||||||
- [ ] It should be easily buildable and publishable using some kind of CI/CD
|
|
||||||
|
|
||||||
## Application Functionality
|
|
||||||
|
|
||||||
- [ ] I should be able to connect one (or many) subjects to a user, so they can start generating as the one
|
|
||||||
- This is meant so that the user is being the "connected subject"
|
|
||||||
- [ ] I need to be able to create the invoices as the connected subject to any subject in current database
|
|
||||||
- Automatically creating non-existing subjects might be nice to have
|
|
||||||
- [ ] I should be able to keep the invoices even if the subject is deleted (or changed) with the data in the day of the
|
|
||||||
creation
|
|
||||||
- [ ] Generating QR Payments is nice to have
|
|
||||||
- [ ] It would be great to automatically check `ares` for data changes from time to time
|
|
|
@ -7,4 +7,8 @@ from . import models
|
||||||
|
|
||||||
@admin.register(models.User)
|
@admin.register(models.User)
|
||||||
class UserAdmin(BaseUserAdmin):
|
class UserAdmin(BaseUserAdmin):
|
||||||
fieldsets = (*BaseUserAdmin.fieldsets, (_('Subjects'), {'fields': ('subjects',)}))
|
fieldsets = (
|
||||||
|
*BaseUserAdmin.fieldsets,
|
||||||
|
(_('Subjects'), {'fields': ('supplier', 'customers')}),
|
||||||
|
)
|
||||||
|
filter_horizontal = (*BaseUserAdmin.filter_horizontal, 'customers')
|
||||||
|
|
|
@ -7,9 +7,6 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from .models import User
|
from .models import User
|
||||||
|
|
||||||
|
|
||||||
# from .models import User
|
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(AuthenticationForm):
|
class LoginForm(AuthenticationForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
@ -22,7 +19,8 @@ class LoginForm(AuthenticationForm):
|
||||||
class RegisterForm(UserCreationForm):
|
class RegisterForm(UserCreationForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = UserCreationForm.Meta.fields + ('first_name', 'last_name', 'email')
|
fields = UserCreationForm.Meta.fields + \
|
||||||
|
('first_name', 'last_name', 'email')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
|
@ -26,11 +26,15 @@ class Migration(migrations.Migration):
|
||||||
verbose_name='ID',
|
verbose_name='ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
(
|
||||||
|
'password', models.CharField(
|
||||||
|
max_length=128, verbose_name='password',
|
||||||
|
),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
'last_login',
|
'last_login',
|
||||||
models.DateTimeField(
|
models.DateTimeField(
|
||||||
blank=True, null=True, verbose_name='last login'
|
blank=True, null=True, verbose_name='last login',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -45,13 +49,13 @@ class Migration(migrations.Migration):
|
||||||
'username',
|
'username',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
error_messages={
|
error_messages={
|
||||||
'unique': 'A user with that username already exists.'
|
'unique': 'A user with that username already exists.',
|
||||||
},
|
},
|
||||||
help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
|
help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
|
||||||
max_length=150,
|
max_length=150,
|
||||||
unique=True,
|
unique=True,
|
||||||
validators=[
|
validators=[
|
||||||
django.contrib.auth.validators.UnicodeUsernameValidator()
|
django.contrib.auth.validators.UnicodeUsernameValidator(),
|
||||||
],
|
],
|
||||||
verbose_name='username',
|
verbose_name='username',
|
||||||
),
|
),
|
||||||
|
@ -59,19 +63,19 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
'first_name',
|
'first_name',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=150, verbose_name='first name'
|
blank=True, max_length=150, verbose_name='first name',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'last_name',
|
'last_name',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=150, verbose_name='last name'
|
blank=True, max_length=150, verbose_name='last name',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'email',
|
'email',
|
||||||
models.EmailField(
|
models.EmailField(
|
||||||
blank=True, max_length=254, verbose_name='email address'
|
blank=True, max_length=254, verbose_name='email address',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
@ -93,7 +97,7 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
'date_joined',
|
'date_joined',
|
||||||
models.DateTimeField(
|
models.DateTimeField(
|
||||||
default=django.utils.timezone.now, verbose_name='date joined'
|
default=django.utils.timezone.now, verbose_name='date joined',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
|
|
|
@ -12,7 +12,9 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='user',
|
model_name='user',
|
||||||
name='email',
|
name='email',
|
||||||
field=models.EmailField(max_length=254, verbose_name='email address'),
|
field=models.EmailField(
|
||||||
|
max_length=254, verbose_name='email address',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='user',
|
model_name='user',
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Generated by Django 5.0.1 on 2024-02-06 18:57
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0004_alter_user_subjects'),
|
||||||
|
('subjects', '0003_alter_subject_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='user',
|
||||||
|
name='subjects',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='customers',
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True, related_name='+', to='subjects.subject',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='suppliers',
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True, related_name='+', to='subjects.subject',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Generated by Django 5.0.1 on 2024-02-16 15:20
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('accounts', '0005_remove_user_subjects_user_customers_user_suppliers'),
|
||||||
|
('subjects', '0003_alter_subject_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='user',
|
||||||
|
name='suppliers',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='user',
|
||||||
|
name='supplier',
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.PROTECT,
|
||||||
|
related_name='supplier',
|
||||||
|
to='subjects.subject',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='user',
|
||||||
|
name='customers',
|
||||||
|
field=models.ManyToManyField(
|
||||||
|
blank=True, to='subjects.subject', verbose_name='customers',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -12,7 +12,18 @@ class User(AbstractUser):
|
||||||
last_name = models.CharField(_('last name'), max_length=150)
|
last_name = models.CharField(_('last name'), max_length=150)
|
||||||
email = models.EmailField(_('email address'))
|
email = models.EmailField(_('email address'))
|
||||||
|
|
||||||
subjects = models.ManyToManyField(Subject, blank=True)
|
supplier = models.ForeignKey(
|
||||||
|
Subject, models.PROTECT, _('supplier'), blank=True, null=True,
|
||||||
|
)
|
||||||
|
customers = models.ManyToManyField(
|
||||||
|
Subject, blank=True, verbose_name=_('customers'),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta(AbstractUser.Meta):
|
class Meta(AbstractUser.Meta):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
def _get_m2m_ids(self, field: str):
|
||||||
|
return list(getattr(self, field).values_list('id', flat=True))
|
||||||
|
|
||||||
|
def get_customers(self) -> list[int]:
|
||||||
|
return self._get_m2m_ids('customers')
|
||||||
|
|
|
@ -19,14 +19,27 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% if request.user.subjects.exists %}
|
{% if request.user.supplier %}
|
||||||
<div class="card mb-2">
|
<div class="card mb-2">
|
||||||
<h5 class="card-header">{% trans "Linked subjects" %}</h5>
|
<h5 class="card-header">{% trans "Current supplier" %}</h5>
|
||||||
<ul class="list-group list-group-flush">
|
<ul class="list-group list-group-flush">
|
||||||
{% for subject in request.user.subjects.all %}
|
{% with supplier_data=request.user.supplier.get_latest_data %}
|
||||||
<li class="list-group-item">{{ subject.name }}</li>
|
<li class="list-group-item">{{ supplier_data.name }}</li>
|
||||||
|
{% endwith %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if request.user.customers.exists %}
|
||||||
|
<div class="card mb-2">
|
||||||
|
<h5 class="card-header">{% trans "Customers" %}</h5>
|
||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
{% for subject in request.user.customers.all %}
|
||||||
|
{% with customer_data=subject.get_latest_data %}
|
||||||
|
<li class="list-group-item">{{ customer_data.name }}</li>
|
||||||
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -59,5 +59,4 @@ def auth_register(req: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def me(req: HttpRequest) -> HttpResponse:
|
def me(req: HttpRequest) -> HttpResponse:
|
||||||
print(req.user.username)
|
|
||||||
return render(req, 'account/me.html')
|
return render(req, 'account/me.html')
|
||||||
|
|
556
db_schema.drawio
Normal file
556
db_schema.drawio
Normal file
|
@ -0,0 +1,556 @@
|
||||||
|
<mxfile modified="2024-06-12T11:17:01.686Z" host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.4.8 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="beYsF54MmV73K3B58AWe" version="24.3.1" type="device">
|
||||||
|
<diagram id="Ht1M8jgEwFfnCIfOTk4-" name="Page-1">
|
||||||
|
<mxGraphModel dx="1434" dy="839" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0" />
|
||||||
|
<mxCell id="1" parent="0" />
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-1" value="User" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="99.94" y="50" width="180" height="300" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-2" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-3" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-2">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-4" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-2">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-5" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-6" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-5">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-7" value="username" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-5">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-8" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-9" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-8">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-10" value="first_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-8">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-18" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-19" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-18">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-20" value="last_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-18">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-21" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-22" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-21">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-23" value="email" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-21">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-24" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-25" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-24">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-26" value="is_staff" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-24">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-27" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="210" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-28" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-27">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-29" value="is_active" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-27">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-30" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="240" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-31" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-30">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-32" value="date_joined" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-30">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-135" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-1">
|
||||||
|
<mxGeometry y="270" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-136" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-135">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-137" value="supplier_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-135">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-44" value="Subject" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="829.94" y="40" width="140" height="240" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-45" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="30" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-46" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-45">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-47" value="CIN" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-45">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-48" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="60" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-49" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-48">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-50" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-48">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-51" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="90" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-52" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-51">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-53" value="vat_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-51">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-54" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="120" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-55" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-54">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-56" value="street" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-54">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-60" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="150" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-61" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-60">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-62" value="zip_code" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-60">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-57" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="180" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-58" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-57">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-59" value="city" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-57">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-66" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-44">
|
||||||
|
<mxGeometry y="210" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-67" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-66">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-68" value="city_part" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-66">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-69" value="Invoice" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="369.94" y="554" width="180" height="210" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-70" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-71" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-70">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-72" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-70">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-73" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-74" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-73">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-75" value="user_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-73">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-76" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-77" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-76">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-78" value="supplier_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-76">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-79" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-80" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-79">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-81" value="customer_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-79">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-85" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-86" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-85">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-87" value="invoice_date" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-85">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-82" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-83" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-82">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-84" value="due_date" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-82">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-88" value="Invoice Item" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="299.94" y="194" width="180" height="210" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-89" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-88">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-90" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-89">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-91" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-89">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-92" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-88">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-93" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-92">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-94" value="invoice_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-92">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-95" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-88">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-96" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-95">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-97" value="amount" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-95">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-98" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-88">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-99" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-98">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-100" value="amount_unit" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-98">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-104" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-88">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-105" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-104">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-106" value="description" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-104">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-101" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-88">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-102" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-101">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-103" value="price_for_amount" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-101">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-107" value="Subject Snapshot" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="679.94" y="394" width="140" height="270" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-108" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="30" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-109" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-108">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-110" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-108">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-111" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="60" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-112" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-111">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-113" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-111">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-114" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="90" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-115" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-114">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-116" value="vat_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-114">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-117" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="120" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-118" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-117">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-119" value="street" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-117">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-120" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="150" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-121" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-120">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-122" value="zip_code" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-120">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-123" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="180" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-124" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-123">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-125" value="city" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-123">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-126" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="210" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-127" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-126">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-128" value="city_part" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-126">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-132" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-107">
|
||||||
|
<mxGeometry y="240" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-133" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-132">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-134" value="subject_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-132">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-241" value="User Subject" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="549.94" y="50" width="180" height="120" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-242" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-241">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-243" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-242">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-244" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-242">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-245" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-241">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-246" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-245">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-247" value="user_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-245">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-248" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-241">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-249" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-248">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-250" value="subject_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-248">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-254" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-2" target="nr37UCySzYaolLaYy_Jx-245">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-255" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-45" target="nr37UCySzYaolLaYy_Jx-248">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-258" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-92" target="nr37UCySzYaolLaYy_Jx-70">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-260" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-73" target="nr37UCySzYaolLaYy_Jx-2">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-261" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-76" target="nr37UCySzYaolLaYy_Jx-108">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-262" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-79" target="nr37UCySzYaolLaYy_Jx-108">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-263" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-132" target="nr37UCySzYaolLaYy_Jx-45">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
523
db_schema_rework.drawio
Normal file
523
db_schema_rework.drawio
Normal file
|
@ -0,0 +1,523 @@
|
||||||
|
<mxfile modified="2024-06-14T19:53:03.931Z" host="Electron" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="FsFUoTxHyPEgeqG1KxWB" version="24.5.3" type="device">
|
||||||
|
<diagram id="Ht1M8jgEwFfnCIfOTk4-" name="Page-1">
|
||||||
|
<mxGraphModel dx="1004" dy="694" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0" />
|
||||||
|
<mxCell id="1" parent="0" />
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-1" value="User" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="99.94" y="50" width="180" height="300" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-2" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-3" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-2" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-4" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-2" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-5" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-6" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-5" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-7" value="username" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-5" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-8" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-9" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-8" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-10" value="first_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-8" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-18" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-19" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-18" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-20" value="last_name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-18" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-21" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-22" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-21" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-23" value="email" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-21" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-24" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-25" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-24" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-26" value="is_staff" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-24" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-27" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="210" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-28" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-27" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-29" value="is_active" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-27" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-30" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="240" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-31" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-30" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-32" value="date_joined" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-30" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-135" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-1" vertex="1">
|
||||||
|
<mxGeometry y="270" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-136" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-135" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-137" value="supplier_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-135" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-44" value="Subject" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="750" y="240" width="140" height="90" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-45" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="nr37UCySzYaolLaYy_Jx-44" vertex="1">
|
||||||
|
<mxGeometry y="30" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-46" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-45" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-47" value="CIN" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-45" vertex="1">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-51" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-44" vertex="1">
|
||||||
|
<mxGeometry y="60" width="140" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-52" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-51" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-53" value="vat_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-51" vertex="1">
|
||||||
|
<mxGeometry x="30" width="110" height="30" as="geometry">
|
||||||
|
<mxRectangle width="110" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-69" value="Invoice" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="440" y="540" width="180" height="270" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-70" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="nr37UCySzYaolLaYy_Jx-69" vertex="1">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-71" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-70" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-72" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-70" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-73" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-69" vertex="1">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-74" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-73" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-75" value="user_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-73" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-76" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-69" vertex="1">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-77" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-76" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-78" value="supplier_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-76" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-1" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-2" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="Sq4IkR5sZP7Z3nL0hjTo-1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-3" value="supplier_data_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="Sq4IkR5sZP7Z3nL0hjTo-1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-79" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-69" vertex="1">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-80" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-79" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-81" value="customer_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-79" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-4" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" vertex="1" parent="nr37UCySzYaolLaYy_Jx-69">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-5" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="Sq4IkR5sZP7Z3nL0hjTo-4">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-6" value="customer_data_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" vertex="1" parent="Sq4IkR5sZP7Z3nL0hjTo-4">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-85" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-69" vertex="1">
|
||||||
|
<mxGeometry y="210" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-86" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-85" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-87" value="invoice_date" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-85" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-82" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-69" vertex="1">
|
||||||
|
<mxGeometry y="240" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-83" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-82" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-84" value="due_date" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-82" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-88" value="Invoice Item" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="299.94" y="194" width="180" height="210" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-89" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="nr37UCySzYaolLaYy_Jx-88" vertex="1">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-90" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-89" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-91" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-89" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-92" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-88" vertex="1">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-93" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-92" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-94" value="invoice_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-92" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-95" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-88" vertex="1">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-96" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-95" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-97" value="amount" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-95" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-98" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-88" vertex="1">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-99" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-98" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-100" value="amount_unit" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-98" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-104" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-88" vertex="1">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-105" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-104" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-106" value="description" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-104" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-101" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-88" vertex="1">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-102" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-101" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-103" value="price_for_amount" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-101" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-241" value="User Subject" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="549.94" y="50" width="180" height="120" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-242" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="nr37UCySzYaolLaYy_Jx-241" vertex="1">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-243" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-242" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-244" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-242" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-245" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-241" vertex="1">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-246" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-245" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-247" value="user_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-245" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-248" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="nr37UCySzYaolLaYy_Jx-241" vertex="1">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-249" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-248" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-250" value="subject_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="nr37UCySzYaolLaYy_Jx-248" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-254" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="nr37UCySzYaolLaYy_Jx-2" target="nr37UCySzYaolLaYy_Jx-245" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-255" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="nr37UCySzYaolLaYy_Jx-45" target="nr37UCySzYaolLaYy_Jx-248" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-258" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" parent="1" source="nr37UCySzYaolLaYy_Jx-92" target="nr37UCySzYaolLaYy_Jx-70" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="nr37UCySzYaolLaYy_Jx-260" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="nr37UCySzYaolLaYy_Jx-73" target="nr37UCySzYaolLaYy_Jx-2" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-1" value="Subject Data" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="930" y="510" width="180" height="270" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-2" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="30" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-3" value="PK" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-2" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-4" value="UUID" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-2" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-5" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="60" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-6" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-5" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-7" value="subject_id" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-5" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-8" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="90" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-9" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-8" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-10" value="name" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-8" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-11" value="" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="120" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-12" value="" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-11" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-13" value="city" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-11" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-18" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="150" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-19" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-18" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-20" value="city_part" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-18" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-21" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="180" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-22" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-21" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-23" value="zip_code" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-21" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-24" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="210" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-25" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-24" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-26" value="street" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-24" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-27" style="shape=tableRow;horizontal=0;startSize=0;swimlaneHead=0;swimlaneBody=0;fillColor=none;collapsible=0;dropTarget=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" parent="zVNAeAY2EM7rbmsBrYKd-1" vertex="1">
|
||||||
|
<mxGeometry y="240" width="180" height="30" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-28" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;editable=1;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-27" vertex="1">
|
||||||
|
<mxGeometry width="30" height="30" as="geometry">
|
||||||
|
<mxRectangle width="30" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-29" value="created_date" style="shape=partialRectangle;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;overflow=hidden;whiteSpace=wrap;html=1;" parent="zVNAeAY2EM7rbmsBrYKd-27" vertex="1">
|
||||||
|
<mxGeometry x="30" width="150" height="30" as="geometry">
|
||||||
|
<mxRectangle width="150" height="30" as="alternateBounds" />
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="zVNAeAY2EM7rbmsBrYKd-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="zVNAeAY2EM7rbmsBrYKd-5" target="nr37UCySzYaolLaYy_Jx-45" edge="1">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sq4IkR5sZP7Z3nL0hjTo-4" target="zVNAeAY2EM7rbmsBrYKd-2">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="Sq4IkR5sZP7Z3nL0hjTo-1" target="zVNAeAY2EM7rbmsBrYKd-2">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-76" target="nr37UCySzYaolLaYy_Jx-45">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="Sq4IkR5sZP7Z3nL0hjTo-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="nr37UCySzYaolLaYy_Jx-79" target="nr37UCySzYaolLaYy_Jx-45">
|
||||||
|
<mxGeometry relative="1" as="geometry" />
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
|
@ -10,6 +10,9 @@ import os
|
||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
|
os.environ.setdefault(
|
||||||
|
'DJANGO_SETTINGS_MODULE',
|
||||||
|
'facturio.settings.development',
|
||||||
|
)
|
||||||
|
|
||||||
application = get_asgi_application()
|
application = get_asgi_application()
|
||||||
|
|
0
facturio/settings/__init__.py
Normal file
0
facturio/settings/__init__.py
Normal file
|
@ -12,18 +12,23 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from environ import Env
|
||||||
|
|
||||||
|
env = Env()
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent.parent
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = 'django-insecure-+l+g3)q1zz2bz7=mz4ys6lhu5uj+=ucj34flm^clo4vb3(wmdp'
|
SECRET_KEY = env(
|
||||||
|
'SECRET_KEY', default='django-insecure-+l+g3)q1zz2bz7=mz4ys6lhu5uj+=ucj34flm^clo4vb3(wmdp',
|
||||||
|
)
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = env.bool("DEBUG", default=True)
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
|
||||||
|
@ -40,6 +45,7 @@ INSTALLED_APPS = [
|
||||||
'crispy_bootstrap5',
|
'crispy_bootstrap5',
|
||||||
'accounts.apps.AccountConfig',
|
'accounts.apps.AccountConfig',
|
||||||
'subjects.apps.SubjectsConfig',
|
'subjects.apps.SubjectsConfig',
|
||||||
|
'invoices.apps.InvoicesConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -80,7 +86,7 @@ DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': BASE_DIR / 'db.sqlite3',
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
1
facturio/settings/development.py
Normal file
1
facturio/settings/development.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from facturio.settings.base import * # noqa
|
1
facturio/settings/production.py
Normal file
1
facturio/settings/production.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
from facturio.settings.base import * # noqa
|
|
@ -15,6 +15,7 @@ urlpatterns = i18n_patterns(
|
||||||
path('', landing_page, name='main-page'),
|
path('', landing_page, name='main-page'),
|
||||||
path('accounts/', include('accounts.urls')),
|
path('accounts/', include('accounts.urls')),
|
||||||
path('subjects/', include('subjects.urls')),
|
path('subjects/', include('subjects.urls')),
|
||||||
|
path('invoices/', include('invoices.urls')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
prefix_default_language=False,
|
prefix_default_language=False,
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,6 +10,9 @@ import os
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
|
os.environ.setdefault(
|
||||||
|
'DJANGO_SETTINGS_MODULE',
|
||||||
|
'facturio.settings.development',
|
||||||
|
)
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
|
0
invoices/__init__.py
Normal file
0
invoices/__init__.py
Normal file
21
invoices/admin.py
Normal file
21
invoices/admin.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
|
class InvoiceItemInline(admin.TabularInline):
|
||||||
|
model = models.InvoiceItem
|
||||||
|
extra = 0
|
||||||
|
readonly_fields = [
|
||||||
|
'amount',
|
||||||
|
'amount_unit',
|
||||||
|
'description',
|
||||||
|
'price_for_amount',
|
||||||
|
]
|
||||||
|
can_delete = False
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(models.Invoice)
|
||||||
|
class InvoiceAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ['__str__', 'invoice_date']
|
||||||
|
inlines = [InvoiceItemInline]
|
6
invoices/apps.py
Normal file
6
invoices/apps.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class InvoicesConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'invoices'
|
60
invoices/forms.py
Normal file
60
invoices/forms.py
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
from crispy_forms import helper
|
||||||
|
from crispy_forms import layout
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
from subjects import models as subject_models
|
||||||
|
|
||||||
|
|
||||||
|
class InvoiceItemForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = models.InvoiceItem
|
||||||
|
fields = ["amount", "amount_unit", "description", "price_for_amount"]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.helper = helper.FormHelper()
|
||||||
|
self.helper.form_show_labels = False
|
||||||
|
|
||||||
|
|
||||||
|
InvoiceItemFormSet = forms.inlineformset_factory(
|
||||||
|
models.Invoice, models.InvoiceItem, form=InvoiceItemForm,
|
||||||
|
fields=["description", "amount", "amount_unit", "price_for_amount"],
|
||||||
|
extra=3, can_delete=False, validate_min=True, min_num=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CreateInvoiceForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = models.Invoice
|
||||||
|
fields = ['customer', 'supplier', 'due_date']
|
||||||
|
widgets = {
|
||||||
|
'due_date': forms.DateInput(attrs={'type': 'date'}),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self._user = kwargs.pop('current_user', None)
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
if self._user.supplier:
|
||||||
|
self.fields["supplier"].queryset = subject_models.Subject.objects.filter(
|
||||||
|
id=self._user.supplier.id,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.fields["supplier"].queryset = subject_models.Subject.objects.none()
|
||||||
|
self.fields["customer"].queryset = self._user.customers
|
||||||
|
|
||||||
|
self.helper = helper.FormHelper()
|
||||||
|
self.helper.form_method = 'post'
|
||||||
|
self.helper.add_input(layout.Submit('submit', _('Save')))
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
invoice = super().save(commit=False)
|
||||||
|
invoice.user = self._user
|
||||||
|
invoice.customer_data = invoice.customer.get_latest_data()
|
||||||
|
invoice.supplier_data = invoice.supplier.get_latest_data()
|
||||||
|
if commit:
|
||||||
|
invoice.save()
|
||||||
|
return invoice
|
126
invoices/migrations/0001_initial.py
Normal file
126
invoices/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
# Generated by Django 5.0.4 on 2024-06-14 20:08
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('subjects', '0004_remove_subject_city_remove_subject_city_part_and_more'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Invoice',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('invoice_date', models.DateField(verbose_name='Invoice date')),
|
||||||
|
('due_date', models.DateField(verbose_name='Due date')),
|
||||||
|
(
|
||||||
|
'customer',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to='subjects.subject',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'customer_data',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to='subjects.subjectdata',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'supplier',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to='subjects.subject',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'supplier_data',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to='subjects.subjectdata',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Invoice',
|
||||||
|
'verbose_name_plural': 'Invoices',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='InvoiceItem',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'amount',
|
||||||
|
models.DecimalField(
|
||||||
|
decimal_places=3, max_digits=8, verbose_name='Amount',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'amount_unit',
|
||||||
|
models.CharField(
|
||||||
|
max_length=32, verbose_name='Amount unit',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'description',
|
||||||
|
models.CharField(
|
||||||
|
max_length=64, verbose_name='Description',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'price_for_amount',
|
||||||
|
models.DecimalField(
|
||||||
|
decimal_places=3, max_digits=8, verbose_name='Price for amount',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'invoice',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='items',
|
||||||
|
to='invoices.invoice',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Invoice Item',
|
||||||
|
'verbose_name_plural': 'Invoice Items',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
21
invoices/migrations/0002_alter_invoice_invoice_date.py
Normal file
21
invoices/migrations/0002_alter_invoice_invoice_date.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-07-04 21:59
|
||||||
|
import django.utils.timezone
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("invoices", "0001_initial"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="invoice",
|
||||||
|
name="invoice_date",
|
||||||
|
field=models.DateField(
|
||||||
|
default=django.utils.timezone.now, verbose_name="Invoice date",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
0
invoices/migrations/__init__.py
Normal file
0
invoices/migrations/__init__.py
Normal file
71
invoices/models.py
Normal file
71
invoices/models.py
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import decimal
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.db import models
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from accounts.models import User
|
||||||
|
|
||||||
|
from subjects import models as subject_models
|
||||||
|
|
||||||
|
UserModel: 'User' = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class Invoice(models.Model):
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Invoice')
|
||||||
|
verbose_name_plural = _('Invoices')
|
||||||
|
|
||||||
|
user = models.ForeignKey(UserModel, models.CASCADE)
|
||||||
|
supplier = models.ForeignKey(
|
||||||
|
subject_models.Subject, on_delete=models.CASCADE, related_name='+', verbose_name=_('Supplier'),
|
||||||
|
)
|
||||||
|
supplier_data = models.ForeignKey(
|
||||||
|
subject_models.SubjectData, on_delete=models.CASCADE, related_name='+', verbose_name=_('Supplier data'),
|
||||||
|
)
|
||||||
|
|
||||||
|
customer = models.ForeignKey(
|
||||||
|
subject_models.Subject, on_delete=models.CASCADE, related_name='+', verbose_name=_('Customer'),
|
||||||
|
)
|
||||||
|
customer_data = models.ForeignKey(
|
||||||
|
subject_models.SubjectData, on_delete=models.CASCADE, related_name='+', verbose_name=_('Customer data'),
|
||||||
|
)
|
||||||
|
invoice_date = models.DateField(_('Invoice date'), default=timezone.now)
|
||||||
|
due_date = models.DateField(_('Due date'))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.id} - {self.supplier_data.name} -> {self.customer_data.name}'
|
||||||
|
|
||||||
|
def total_price(self) -> decimal.Decimal:
|
||||||
|
total = decimal.Decimal(0)
|
||||||
|
for item in self.items.all():
|
||||||
|
total += item.total_price()
|
||||||
|
return total
|
||||||
|
|
||||||
|
def custom_id(self) -> str:
|
||||||
|
return f"{self.invoice_date.year}-{self.id:04}"
|
||||||
|
|
||||||
|
|
||||||
|
class InvoiceItem(models.Model):
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Invoice Item')
|
||||||
|
verbose_name_plural = _('Invoice Items')
|
||||||
|
|
||||||
|
invoice = models.ForeignKey(
|
||||||
|
Invoice, on_delete=models.CASCADE, related_name='items',
|
||||||
|
)
|
||||||
|
amount = models.DecimalField(_('Amount'), decimal_places=3, max_digits=8)
|
||||||
|
amount_unit = models.CharField(_('Amount unit'), max_length=32)
|
||||||
|
description = models.CharField(_('Description'), max_length=64)
|
||||||
|
price_for_amount = models.DecimalField(
|
||||||
|
_('Price for amount'), decimal_places=3, max_digits=8,
|
||||||
|
)
|
||||||
|
|
||||||
|
def total_price(self) -> decimal.Decimal:
|
||||||
|
return self.amount * self.price_for_amount
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.id} -> {self.invoice.id}'
|
112
invoices/static/css/invoice.css
Normal file
112
invoices/static/css/invoice.css
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: var(--font-family), sans-serif;
|
||||||
|
color: var(--main-color);
|
||||||
|
background-color: var(--background-color);
|
||||||
|
margin: 10mm 10mm;
|
||||||
|
}
|
||||||
|
}
|
55
invoices/static/js/formset_mngr.js
Normal file
55
invoices/static/js/formset_mngr.js
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
document.addEventListener("DOMContentLoaded", (event) => {
|
||||||
|
const totalForms = document.getElementById("id_items-TOTAL_FORMS")
|
||||||
|
const initialForms = document.getElementById("id_items-INITIAL_FORMS")
|
||||||
|
const minForms = document.getElementById("id_items-MIN_NUM_FORMS")
|
||||||
|
const maxForms = document.getElementById("id_items-MAX_NUM_FORMS")
|
||||||
|
const formsetContainer = document.getElementById("formset-container")
|
||||||
|
|
||||||
|
console.log(totalForms.value, initialForms.value, minForms.value, maxForms.value, formsetContainer)
|
||||||
|
|
||||||
|
const renumberAll = () => {
|
||||||
|
let id = 0;
|
||||||
|
formsetContainer.querySelectorAll("tr").forEach(row => {
|
||||||
|
row.querySelectorAll("[name^='items-'], [id^='id_items-']").forEach(element => {
|
||||||
|
const namePattern = /items-(\d+)-/;
|
||||||
|
const idPattern = /id_items-(\d+)-/;
|
||||||
|
element.name = element.name.replace(namePattern, `items-${id}-`);
|
||||||
|
element.id = element.id.replace(idPattern, `id_items-${id}-`);
|
||||||
|
});
|
||||||
|
id += 1;
|
||||||
|
});
|
||||||
|
totalForms.value = id; // Update the total form count
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearValues = (node) => {
|
||||||
|
node.querySelectorAll("input").forEach(element => {
|
||||||
|
if (element.type === "checkbox" || element.type === "radio") {
|
||||||
|
element.checked = false;
|
||||||
|
} else {
|
||||||
|
element.value = "";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("add-formset-item").addEventListener("click", () => {
|
||||||
|
if (parseInt(totalForms.value) >= parseInt(maxForms.value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const template = formsetContainer.firstElementChild;
|
||||||
|
const newForm = template.cloneNode(true)
|
||||||
|
formsetContainer.appendChild(newForm)
|
||||||
|
clearValues(newForm)
|
||||||
|
|
||||||
|
renumberAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
formsetContainer.addEventListener("click", (event) => {
|
||||||
|
if (event.target.classList.contains("remove-formset-item") && (parseInt(totalForms.value) > parseInt(minForms.value))) {
|
||||||
|
const clickedButton = event.target
|
||||||
|
clickedButton.closest("tr").remove()
|
||||||
|
renumberAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
78
invoices/templates/invoices/index.html
Normal file
78
invoices/templates/invoices/index.html
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
{% extends "facturio/base.html" %}
|
||||||
|
{% load crispy_forms_filters %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Invoices" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Invoices" %}</h1>
|
||||||
|
<div class="container mb-4">
|
||||||
|
<h2>{% trans "Create invoice" %}</h2>
|
||||||
|
<form method="post" enctype="multipart/form-data">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form|crispy }}
|
||||||
|
{{ formset.management_form }}
|
||||||
|
<table id="formset-table" class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{% for field in formset.empty_form.visible_fields %}
|
||||||
|
<th>{{ field.label }}</th>
|
||||||
|
{% endfor %}
|
||||||
|
<th>{% trans "Actions" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="formset-container">
|
||||||
|
{% for formset_form in formset %}
|
||||||
|
<tr class="formset-item">
|
||||||
|
{% for field in formset_form.visible_fields %}
|
||||||
|
<td>{{ field|as_crispy_field }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
<td>
|
||||||
|
<button type="button"
|
||||||
|
class="remove-formset-item btn btn-danger">{% trans "Remove" %}</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button type="button" id="add-formset-item" class="btn btn-secondary">{% trans "Add More" %}</button>
|
||||||
|
<button type="submit" class="btn btn-primary">{% trans "Create" %}</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h2>{% trans "Existing invoices" %}</h2>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Invoice date" %}</th>
|
||||||
|
<th>{% trans "Supplier" %}</th>
|
||||||
|
<th>{% trans "Customer" %}</th>
|
||||||
|
<th>{% trans "Due date" %}</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for invoice in invoices %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ invoice.invoice_date }}</td>
|
||||||
|
<td>{{ invoice.supplier_data.name }}</td>
|
||||||
|
<td>{{ invoice.customer_data.name }}</td>
|
||||||
|
<td>{{ invoice.due_date }}</td>
|
||||||
|
<td><a href="{% url 'invoices:invoice' invoice_id=invoice.id %}"
|
||||||
|
class="links">{% trans "Show" %}</a></td>
|
||||||
|
<td><a href="{% url 'invoices:print_invoice' invoice_id=invoice.id %}"
|
||||||
|
class="links">{% trans "Print" %}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script src="{% static 'js/formset_mngr.js' %}" defer></script>
|
||||||
|
{% endblock %}
|
202
invoices/templates/invoices/invoice.html
Normal file
202
invoices/templates/invoices/invoice.html
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
{% load i18n %}
|
||||||
|
<!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), sans-serif;
|
||||||
|
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>{% trans "Invoice" %} <span class="invoice-id">{{ invoice.custom_id }}</span></h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="parties-section">
|
||||||
|
<div class="parties">
|
||||||
|
<h2>{% trans "Supplier" %}</h2>
|
||||||
|
<ul>
|
||||||
|
{% with invoice.supplier_data as sd %}
|
||||||
|
<li>{{ sd.name }}</li>
|
||||||
|
<li>{{ sd.street }}</li>
|
||||||
|
<li>{{ sd.city }} - {{ sd.city_part }}, {{ sd.zip_code }}</li>
|
||||||
|
<p></p>
|
||||||
|
<li>{% trans "CIN" %}: {{ invoice.supplier.id }}</li>
|
||||||
|
{% if invoice.supplier.vat_id %}
|
||||||
|
<li>{% trans "VAT ID" %}: {{ invoice.supplier.vat_id }}</li>
|
||||||
|
{% endif %}
|
||||||
|
<p></p>
|
||||||
|
<li>Bankovní účet: TODO</li>
|
||||||
|
{% endwith %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="parties">
|
||||||
|
<h2>{% trans "Customer" %}</h2>
|
||||||
|
<ul>
|
||||||
|
{% with invoice.customer_data as cd %}
|
||||||
|
<li>{{ cd.name }}</li>
|
||||||
|
<li>{{ cd.street }}</li>
|
||||||
|
<li>{{ cd.city }} - {{ cd.city_part }}, {{ cd.zip_code }}</li>
|
||||||
|
<p></p>
|
||||||
|
<li>{% trans "CIN" %}: {{ invoice.customer.id }}</li>
|
||||||
|
{% if invoice.customer.vat_id %}
|
||||||
|
<li>{% trans "VAT ID" %}: {{ invoice.customer.vat_id }}</li>
|
||||||
|
{% endif %}
|
||||||
|
<p></p>
|
||||||
|
<li><strong>{% trans "Invoice date" %}:</strong> {{ invoice.invoice_date }}</li>
|
||||||
|
<li><strong>{% trans "Due date" %}:</strong> {{ invoice.due_date }}</li>
|
||||||
|
{% endwith %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>{% trans "Invoice details" %}</h2>
|
||||||
|
<table id="invoice">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="small-col">{% trans "Amount" %}</th>
|
||||||
|
<th class="small-col">{% trans "Amount unit" %}</th>
|
||||||
|
<th class="big-col">{% trans "Description" %}</th>
|
||||||
|
<th class="medium-col right-align">{% trans "Price for amount" %}</th>
|
||||||
|
<th class="medium-col right-align">{% trans "Total" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for invoice_item in invoice.items.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ invoice_item.amount.normalize }}</td>
|
||||||
|
<td>{{ invoice_item.amount_unit }}</td>
|
||||||
|
<td>{{ invoice_item.description }}</td>
|
||||||
|
<td class="right-align">{{ invoice_item.price_for_amount.normalize }} Kč</td>
|
||||||
|
<td class="right-align">{{ invoice_item.total_price.normalize }} Kč</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="invoice-total">
|
||||||
|
<p><strong>{% trans "Total" %}: {{ invoice.total_price.normalize }} 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>
|
85
invoices/templates/invoices/view.html
Normal file
85
invoices/templates/invoices/view.html
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
{% extends "facturio/base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% block title %}{% trans "Invoice" %}{% endblock %}
|
||||||
|
{% block head %}
|
||||||
|
<link rel="stylesheet" href="{% static "css/invoice.css" %}">
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<header>
|
||||||
|
<h1>{% trans "Invoice" %} <span class="invoice-id">{{ invoice.custom_id }}</span></h1>
|
||||||
|
</header>
|
||||||
|
<section class="parties-section">
|
||||||
|
<div class="parties">
|
||||||
|
<h2>{% trans "Supplier" %}</h2>
|
||||||
|
<ul>
|
||||||
|
{% with invoice.supplier_data as sd %}
|
||||||
|
<li>{{ sd.name }}</li>
|
||||||
|
<li>{{ sd.street }}</li>
|
||||||
|
<li>{{ sd.city }} - {{ sd.city_part }}, {{ sd.zip_code }}</li>
|
||||||
|
<p></p>
|
||||||
|
<li>{% trans "CIN" %}: {{ invoice.supplier.id }}</li>
|
||||||
|
{% if invoice.supplier.vat_id %}
|
||||||
|
<li>{% trans "VAT ID" %}: {{ invoice.supplier.vat_id }}</li>
|
||||||
|
{% endif %}
|
||||||
|
<p></p>
|
||||||
|
<li>Bankovní účet: TODO</li>
|
||||||
|
{% endwith %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="parties">
|
||||||
|
<h2>{% trans "Customer" %}</h2>
|
||||||
|
<ul>
|
||||||
|
{% with invoice.customer_data as cd %}
|
||||||
|
<li>{{ cd.name }}</li>
|
||||||
|
<li>{{ cd.street }}</li>
|
||||||
|
<li>{{ cd.city }} - {{ cd.city_part }}, {{ cd.zip_code }}</li>
|
||||||
|
<p></p>
|
||||||
|
<li>{% trans "CIN" %}: {{ invoice.customer.id }}</li>
|
||||||
|
{% if invoice.customer.vat_id %}
|
||||||
|
<li>{% trans "VAT ID" %}: {{ invoice.customer.vat_id }}</li>
|
||||||
|
{% endif %}
|
||||||
|
<p></p>
|
||||||
|
<li><strong>{% trans "Invoice date" %}:</strong> {{ invoice.invoice_date }}</li>
|
||||||
|
<li><strong>{% trans "Due date" %}:</strong> {{ invoice.due_date }}</li>
|
||||||
|
{% endwith %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h2>{% trans "Invoice details" %}</h2>
|
||||||
|
<table id="invoice">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="small-col">{% trans "Amount" %}</th>
|
||||||
|
<th class="small-col">{% trans "Amount unit" %}</th>
|
||||||
|
<th class="big-col">{% trans "Description" %}</th>
|
||||||
|
<th class="medium-col right-align">{% trans "Price for amount" %}</th>
|
||||||
|
<th class="medium-col right-align">{% trans "Total" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for invoice_item in invoice.items.all %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ invoice_item.amount.normalize }}</td>
|
||||||
|
<td>{{ invoice_item.amount_unit }}</td>
|
||||||
|
<td>{{ invoice_item.description }}</td>
|
||||||
|
<td class="right-align">{{ invoice_item.price_for_amount.normalize }} Kč</td>
|
||||||
|
<td class="right-align">{{ invoice_item.total_price.normalize }} Kč</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="invoice-total">
|
||||||
|
<p><strong>{% trans "Total" %}: {{ invoice.total_price.normalize }} Kč</strong></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Fyzická osoba zapsaná v živnostenském rejstříku.</p>
|
||||||
|
<p>Fakturu vygenerovala aplikace Facturio</p>
|
||||||
|
</footer>
|
||||||
|
{% endblock %}
|
1
invoices/tests.py
Normal file
1
invoices/tests.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Create your tests here.
|
11
invoices/urls.py
Normal file
11
invoices/urls.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
app_name = 'invoices'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', views.home, name='index'),
|
||||||
|
path('<int:invoice_id>', views.view_invoice, name='invoice'),
|
||||||
|
path('print/<int:invoice_id>', views.print_invoice, name='print_invoice'),
|
||||||
|
]
|
52
invoices/views.py
Normal file
52
invoices/views.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.db import transaction
|
||||||
|
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 forms
|
||||||
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def home(req: HttpRequest) -> HttpResponse:
|
||||||
|
user_invoices = models.Invoice.objects.filter(user=req.user).all()
|
||||||
|
|
||||||
|
if req.method == 'POST':
|
||||||
|
form = forms.CreateInvoiceForm(data=req.POST, current_user=req.user)
|
||||||
|
if form.is_valid():
|
||||||
|
with transaction.atomic():
|
||||||
|
invoice = form.save()
|
||||||
|
formset = forms.InvoiceItemFormSet(
|
||||||
|
data=req.POST, instance=invoice,
|
||||||
|
)
|
||||||
|
if formset.is_valid():
|
||||||
|
formset.save()
|
||||||
|
return redirect(reverse('invoices:invoice', kwargs=dict(invoice_id=invoice.id)))
|
||||||
|
else:
|
||||||
|
transaction.set_rollback(True)
|
||||||
|
else:
|
||||||
|
formset = forms.InvoiceItemFormSet(data=req.POST)
|
||||||
|
|
||||||
|
return render(req, 'invoices/index.html', dict(form=form, formset=formset, invoices=user_invoices))
|
||||||
|
|
||||||
|
elif req.method == 'GET':
|
||||||
|
form = forms.CreateInvoiceForm(current_user=req.user)
|
||||||
|
formset = forms.InvoiceItemFormSet()
|
||||||
|
return render(req, 'invoices/index.html', dict(form=form, formset=formset, invoices=user_invoices))
|
||||||
|
|
||||||
|
return HttpResponse(status=405)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def view_invoice(req: HttpRequest, invoice_id: int) -> HttpResponse:
|
||||||
|
invoice = models.Invoice.objects.get(pk=invoice_id)
|
||||||
|
return render(req, 'invoices/view.html', dict(invoice=invoice))
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def print_invoice(req: HttpRequest, invoice_id: int):
|
||||||
|
invoice = models.Invoice.objects.get(pk=invoice_id)
|
||||||
|
return render(req, 'invoices/invoice.html', dict(invoice=invoice))
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-02-01 20:43+0000\n"
|
"POT-Creation-Date: 2024-08-16 18:53+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -19,18 +19,18 @@ msgstr ""
|
||||||
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n "
|
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n "
|
||||||
"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
"<= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
|
||||||
|
|
||||||
#: accounts/admin.py:12 subjects/models.py:9
|
#: accounts/admin.py:12 subjects/models.py:8
|
||||||
#: subjects/templates/subjects/index.html:4 templates/facturio/base.html:20
|
#: subjects/templates/subjects/index.html:6 templates/facturio/base.html:21
|
||||||
msgid "Subjects"
|
msgid "Subjects"
|
||||||
msgstr "Subjekty"
|
msgstr "Subjekty"
|
||||||
|
|
||||||
#: accounts/forms.py:17 accounts/templates/account/login.html:6
|
#: accounts/forms.py:16 accounts/templates/account/login.html:6
|
||||||
#: templates/facturio/base.html:42
|
#: templates/facturio/base.html:41
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Přihlásit se"
|
msgstr "Přihlásit se"
|
||||||
|
|
||||||
#: accounts/forms.py:30 accounts/templates/account/register.html:6
|
#: accounts/forms.py:30 accounts/templates/account/register.html:6
|
||||||
#: templates/facturio/base.html:45
|
#: templates/facturio/base.html:44
|
||||||
msgid "Register"
|
msgid "Register"
|
||||||
msgstr "Registrovat se"
|
msgstr "Registrovat se"
|
||||||
|
|
||||||
|
@ -46,6 +46,14 @@ msgstr "přijmení"
|
||||||
msgid "email address"
|
msgid "email address"
|
||||||
msgstr "emailová adresa"
|
msgstr "emailová adresa"
|
||||||
|
|
||||||
|
#: accounts/models.py:16
|
||||||
|
msgid "supplier"
|
||||||
|
msgstr "dodavatel"
|
||||||
|
|
||||||
|
#: accounts/models.py:19
|
||||||
|
msgid "customers"
|
||||||
|
msgstr "odběratelé"
|
||||||
|
|
||||||
#: accounts/templates/account/me.html:4 accounts/templates/account/me.html:7
|
#: accounts/templates/account/me.html:4 accounts/templates/account/me.html:7
|
||||||
msgid "About Me"
|
msgid "About Me"
|
||||||
msgstr "O mně"
|
msgstr "O mně"
|
||||||
|
@ -65,95 +73,252 @@ msgstr "Uživatelské jméno: %(username)s"
|
||||||
msgid "Email: %(email)s"
|
msgid "Email: %(email)s"
|
||||||
msgstr "Email: %(email)s"
|
msgstr "Email: %(email)s"
|
||||||
|
|
||||||
#: accounts/templates/account/me.html:24
|
#: accounts/templates/account/me.html:24 subjects/forms.py:53
|
||||||
msgid "Linked subjects"
|
msgid "Current supplier"
|
||||||
msgstr "Propojené Subjekty"
|
msgstr "Aktuální dodavatel"
|
||||||
|
|
||||||
#: facturio/settings.py:109
|
#: accounts/templates/account/me.html:34
|
||||||
|
#: subjects/templates/subjects/index.html:11
|
||||||
|
#: subjects/templates/subjects/index.html:22
|
||||||
|
#: subjects/templates/subjects/index.html:60
|
||||||
|
msgid "Customers"
|
||||||
|
msgstr "Zákazníci"
|
||||||
|
|
||||||
|
#: facturio/settings/base.py:114
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "Angličtina"
|
msgstr "Angličtina"
|
||||||
|
|
||||||
#: facturio/settings.py:110
|
#: facturio/settings/base.py:114
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr "Čeština"
|
msgstr "Čeština"
|
||||||
|
|
||||||
#: subjects/forms.py:14
|
#: invoices/forms.py:51 subjects/forms.py:66
|
||||||
msgid "Your provided CIN is not correct."
|
msgid "Save"
|
||||||
msgstr "Vaše poskytnuté IČO není správné."
|
msgstr "Uložit"
|
||||||
|
|
||||||
#: subjects/forms.py:15
|
#: invoices/models.py:19 invoices/templates/invoices/invoice.html:125
|
||||||
msgid "Subject with provided CIN already exists."
|
#: invoices/templates/invoices/view.html:4
|
||||||
msgstr "Subjekt s poskytnutým IČO již existuje."
|
#: invoices/templates/invoices/view.html:10
|
||||||
|
msgid "Invoice"
|
||||||
|
msgstr "Faktura"
|
||||||
|
|
||||||
#: subjects/forms.py:18 subjects/models.py:12
|
#: invoices/models.py:20 invoices/templates/invoices/index.html:8
|
||||||
#: subjects/templates/subjects/index.html:11
|
#: invoices/templates/invoices/index.html:11 templates/facturio/base.html:24
|
||||||
|
msgid "Invoices"
|
||||||
|
msgstr "Faktury"
|
||||||
|
|
||||||
|
#: invoices/models.py:24 invoices/templates/invoices/index.html:53
|
||||||
|
#: invoices/templates/invoices/invoice.html:130
|
||||||
|
#: invoices/templates/invoices/view.html:14
|
||||||
|
msgid "Supplier"
|
||||||
|
msgstr "Dodavatel"
|
||||||
|
|
||||||
|
#: invoices/models.py:27
|
||||||
|
msgid "Supplier data"
|
||||||
|
msgstr "Informace o dodavateli"
|
||||||
|
|
||||||
|
#: invoices/models.py:31 invoices/templates/invoices/index.html:54
|
||||||
|
#: invoices/templates/invoices/invoice.html:148
|
||||||
|
#: invoices/templates/invoices/view.html:32
|
||||||
|
msgid "Customer"
|
||||||
|
msgstr "Zákazník"
|
||||||
|
|
||||||
|
#: invoices/models.py:34
|
||||||
|
msgid "Customer data"
|
||||||
|
msgstr "Informace o zákazníkovi"
|
||||||
|
|
||||||
|
#: invoices/models.py:36 invoices/templates/invoices/index.html:52
|
||||||
|
#: invoices/templates/invoices/invoice.html:160
|
||||||
|
#: invoices/templates/invoices/view.html:44
|
||||||
|
msgid "Invoice date"
|
||||||
|
msgstr "Datum vystavení"
|
||||||
|
|
||||||
|
#: invoices/models.py:37 invoices/templates/invoices/index.html:55
|
||||||
|
#: invoices/templates/invoices/invoice.html:161
|
||||||
|
#: invoices/templates/invoices/view.html:45
|
||||||
|
msgid "Due date"
|
||||||
|
msgstr "Datum splatnosti"
|
||||||
|
|
||||||
|
#: invoices/models.py:53
|
||||||
|
msgid "Invoice Item"
|
||||||
|
msgstr "Prvek faktury"
|
||||||
|
|
||||||
|
#: invoices/models.py:54
|
||||||
|
msgid "Invoice Items"
|
||||||
|
msgstr "Prvky Faktury"
|
||||||
|
|
||||||
|
#: invoices/models.py:59 invoices/templates/invoices/invoice.html:172
|
||||||
|
#: invoices/templates/invoices/view.html:56
|
||||||
|
msgid "Amount"
|
||||||
|
msgstr "Množství"
|
||||||
|
|
||||||
|
#: invoices/models.py:60 invoices/templates/invoices/invoice.html:173
|
||||||
|
#: invoices/templates/invoices/view.html:57
|
||||||
|
msgid "Amount unit"
|
||||||
|
msgstr "Množstevní jednotka"
|
||||||
|
|
||||||
|
#: invoices/models.py:61 invoices/templates/invoices/invoice.html:174
|
||||||
|
#: invoices/templates/invoices/view.html:58
|
||||||
|
msgid "Description"
|
||||||
|
msgstr "Popis"
|
||||||
|
|
||||||
|
#: invoices/models.py:63 invoices/templates/invoices/invoice.html:175
|
||||||
|
#: invoices/templates/invoices/view.html:59
|
||||||
|
msgid "Price for amount"
|
||||||
|
msgstr "Cena za MJ"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:13
|
||||||
|
msgid "Create invoice"
|
||||||
|
msgstr "Vytvořit fakturu"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:24
|
||||||
|
msgid "Actions"
|
||||||
|
msgstr "Akce"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:35
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "Odebrat"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:42
|
||||||
|
msgid "Add More"
|
||||||
|
msgstr "Přidat další"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:43
|
||||||
|
msgid "Create"
|
||||||
|
msgstr "Vytvořit"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:48
|
||||||
|
msgid "Existing invoices"
|
||||||
|
msgstr "Existující faktury"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:68
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "Zobrazit"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/index.html:70
|
||||||
|
msgid "Print"
|
||||||
|
msgstr "Tisk"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/invoice.html:137
|
||||||
|
#: invoices/templates/invoices/invoice.html:155
|
||||||
|
#: invoices/templates/invoices/view.html:21
|
||||||
|
#: invoices/templates/invoices/view.html:39 subjects/forms.py:20
|
||||||
|
#: subjects/models.py:10 subjects/templates/subjects/index.html:15
|
||||||
|
#: subjects/templates/subjects/index.html:53
|
||||||
msgid "CIN"
|
msgid "CIN"
|
||||||
msgstr "IČO"
|
msgstr "IČO"
|
||||||
|
|
||||||
#: subjects/forms.py:20
|
#: invoices/templates/invoices/invoice.html:139
|
||||||
msgid "Enter the subject CIN, rest will be generated automatically"
|
#: invoices/templates/invoices/invoice.html:157
|
||||||
msgstr "Zadejte IČO subjektu, zbytek bude generován automaticky"
|
#: invoices/templates/invoices/view.html:23
|
||||||
|
#: invoices/templates/invoices/view.html:41 subjects/models.py:12
|
||||||
#: subjects/forms.py:28
|
#: subjects/templates/subjects/index.html:16
|
||||||
msgid "Add"
|
#: subjects/templates/subjects/index.html:54
|
||||||
msgstr "Vytvořit"
|
|
||||||
|
|
||||||
#: subjects/models.py:8
|
|
||||||
msgid "Subject"
|
|
||||||
msgstr "Subjekt"
|
|
||||||
|
|
||||||
#: subjects/models.py:18 subjects/templates/subjects/index.html:12
|
|
||||||
msgid "Name"
|
|
||||||
msgstr "Jméno"
|
|
||||||
|
|
||||||
#: subjects/models.py:23 subjects/templates/subjects/index.html:13
|
|
||||||
msgid "VAT ID"
|
msgid "VAT ID"
|
||||||
msgstr "DIČ"
|
msgstr "DIČ"
|
||||||
|
|
||||||
#: subjects/models.py:30 subjects/templates/subjects/index.html:14
|
#: invoices/templates/invoices/invoice.html:168
|
||||||
|
#: invoices/templates/invoices/view.html:52
|
||||||
|
msgid "Invoice details"
|
||||||
|
msgstr "Detaily faktury"
|
||||||
|
|
||||||
|
#: invoices/templates/invoices/invoice.html:176
|
||||||
|
#: invoices/templates/invoices/invoice.html:193
|
||||||
|
#: invoices/templates/invoices/view.html:60
|
||||||
|
#: invoices/templates/invoices/view.html:77
|
||||||
|
msgid "Total"
|
||||||
|
msgstr "Celkem"
|
||||||
|
|
||||||
|
#: subjects/forms.py:16
|
||||||
|
msgid "Your provided CIN is not correct."
|
||||||
|
msgstr "Vaše poskytnuté IČO není správné."
|
||||||
|
|
||||||
|
#: subjects/forms.py:17
|
||||||
|
msgid "Subject with provided CIN already exists."
|
||||||
|
msgstr "Subjekt s poskytnutým IČO již existuje."
|
||||||
|
|
||||||
|
#: subjects/forms.py:23
|
||||||
|
msgid "Enter the subject CIN, rest will be generated automatically"
|
||||||
|
msgstr "Zadejte IČO subjektu, zbytek bude generován automaticky"
|
||||||
|
|
||||||
|
#: subjects/forms.py:32
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Vytvořit"
|
||||||
|
|
||||||
|
#: subjects/models.py:7
|
||||||
|
msgid "Subject"
|
||||||
|
msgstr "Subjekt"
|
||||||
|
|
||||||
|
#: subjects/models.py:26
|
||||||
|
msgid "Subject Data"
|
||||||
|
msgstr "Data Subjektu"
|
||||||
|
|
||||||
|
#: subjects/models.py:27
|
||||||
|
msgid "Subject Datas"
|
||||||
|
msgstr "Data Subjektů"
|
||||||
|
|
||||||
|
#: subjects/models.py:32 subjects/templates/subjects/index.html:17
|
||||||
|
#: subjects/templates/subjects/index.html:55
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "Jméno"
|
||||||
|
|
||||||
|
#: subjects/models.py:33 subjects/templates/subjects/index.html:20
|
||||||
|
#: subjects/templates/subjects/index.html:58
|
||||||
msgid "Street"
|
msgid "Street"
|
||||||
msgstr "Ulice"
|
msgstr "Ulice"
|
||||||
|
|
||||||
#: subjects/models.py:35 subjects/templates/subjects/index.html:15
|
#: subjects/models.py:34 subjects/templates/subjects/index.html:21
|
||||||
|
#: subjects/templates/subjects/index.html:59
|
||||||
msgid "Zip Code"
|
msgid "Zip Code"
|
||||||
msgstr "PSČ"
|
msgstr "PSČ"
|
||||||
|
|
||||||
#: subjects/models.py:40 subjects/templates/subjects/index.html:16
|
#: subjects/models.py:35 subjects/templates/subjects/index.html:18
|
||||||
|
#: subjects/templates/subjects/index.html:56
|
||||||
msgid "City"
|
msgid "City"
|
||||||
msgstr "Město"
|
msgstr "Město"
|
||||||
|
|
||||||
#: subjects/models.py:45 subjects/templates/subjects/index.html:17
|
#: subjects/models.py:37 subjects/templates/subjects/index.html:19
|
||||||
|
#: subjects/templates/subjects/index.html:57
|
||||||
msgid "City part"
|
msgid "City part"
|
||||||
msgstr "Část města"
|
msgstr "Část města"
|
||||||
|
|
||||||
|
#: subjects/models.py:39
|
||||||
|
msgid "Created date"
|
||||||
|
msgstr "Datum vytvoření"
|
||||||
|
|
||||||
#: subjects/templates/subjects/create.html:6
|
#: subjects/templates/subjects/create.html:6
|
||||||
msgid "Create Subjects"
|
msgid "Create Subjects"
|
||||||
msgstr "Vytvořit Subjekty"
|
msgstr "Vytvořit Subjekty"
|
||||||
|
|
||||||
#: subjects/templates/subjects/index.html:7
|
#: subjects/templates/subjects/index.html:31
|
||||||
|
#: subjects/templates/subjects/index.html:69
|
||||||
|
msgid "None"
|
||||||
|
msgstr "Žádný"
|
||||||
|
|
||||||
|
#: subjects/templates/subjects/index.html:40
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Zrušit"
|
||||||
|
|
||||||
|
#: subjects/templates/subjects/index.html:48
|
||||||
|
msgid "Others"
|
||||||
|
msgstr "Ostatní"
|
||||||
|
|
||||||
|
#: subjects/templates/subjects/index.html:49
|
||||||
msgid "Add new"
|
msgid "Add new"
|
||||||
msgstr "Přidat nový"
|
msgstr "Přidat nový"
|
||||||
|
|
||||||
#: subjects/templates/subjects/index.html:18
|
#: subjects/templates/subjects/index.html:78
|
||||||
msgid "Connect"
|
msgid "Select"
|
||||||
msgstr "Propojit"
|
msgstr "Vybrat"
|
||||||
|
|
||||||
#: subjects/templates/subjects/index.html:35
|
|
||||||
msgid "Link"
|
|
||||||
msgstr "Propojit"
|
|
||||||
|
|
||||||
#: subjects/templates/subjects/index.html:38
|
|
||||||
msgid "Unlink"
|
|
||||||
msgstr "Odpojit"
|
|
||||||
|
|
||||||
#: templates/facturio/base.html:8 templates/facturio/index.html:4
|
#: templates/facturio/base.html:8 templates/facturio/index.html:4
|
||||||
msgid "App"
|
msgid "App"
|
||||||
msgstr "Aplikace"
|
msgstr "Aplikace"
|
||||||
|
|
||||||
#: templates/facturio/base.html:34
|
#: templates/facturio/base.html:33
|
||||||
msgid "Profile"
|
msgid "Profile"
|
||||||
msgstr "Profil"
|
msgstr "Profil"
|
||||||
|
|
||||||
#: templates/facturio/base.html:37
|
#: templates/facturio/base.html:36
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Odhlásit se"
|
msgstr "Odhlásit se"
|
||||||
|
|
|
@ -6,14 +6,17 @@ import sys
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Run administrative tasks."""
|
"""Run administrative tasks."""
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
|
os.environ.setdefault(
|
||||||
|
'DJANGO_SETTINGS_MODULE',
|
||||||
|
'facturio.settings.development',
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
raise ImportError(
|
raise ImportError(
|
||||||
"Couldn't import Django. Are you sure it's installed and "
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
'available on your PYTHONPATH environment variable? Did you '
|
'available on your PYTHONPATH environment variable? Did you '
|
||||||
'forget to activate a virtual environment?'
|
'forget to activate a virtual environment?',
|
||||||
) from exc
|
) from exc
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
78
poetry.lock
generated
78
poetry.lock
generated
|
@ -1,4 +1,4 @@
|
||||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ares-util"
|
name = "ares-util"
|
||||||
|
@ -16,13 +16,13 @@ requests = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "asgiref"
|
name = "asgiref"
|
||||||
version = "3.7.2"
|
version = "3.8.1"
|
||||||
description = "ASGI specs, helper code, and adapters"
|
description = "ASGI specs, helper code, and adapters"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "asgiref-3.7.2-py3-none-any.whl", hash = "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e"},
|
{file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"},
|
||||||
{file = "asgiref-3.7.2.tar.gz", hash = "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed"},
|
{file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
@ -30,13 +30,13 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2023.11.17"
|
version = "2024.6.2"
|
||||||
description = "Python package for providing Mozilla's CA Bundle."
|
description = "Python package for providing Mozilla's CA Bundle."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
{file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"},
|
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
|
||||||
{file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
|
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -158,13 +158,13 @@ test = ["pytest", "pytest-django"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django"
|
name = "django"
|
||||||
version = "5.0.1"
|
version = "5.0.6"
|
||||||
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.10"
|
python-versions = ">=3.10"
|
||||||
files = [
|
files = [
|
||||||
{file = "Django-5.0.1-py3-none-any.whl", hash = "sha256:f47a37a90b9bbe2c8ec360235192c7fddfdc832206fcf618bb849b39256affc1"},
|
{file = "Django-5.0.6-py3-none-any.whl", hash = "sha256:8363ac062bb4ef7c3f12d078f6fa5d154031d129a15170a1066412af49d30905"},
|
||||||
{file = "Django-5.0.1.tar.gz", hash = "sha256:8c8659665bc6e3a44fefe1ab0a291e5a3fb3979f9a8230be29de975e57e8f854"},
|
{file = "Django-5.0.6.tar.gz", hash = "sha256:ff1b61005004e476e0aeea47c7f79b85864c70124030e95146315396f1e7951f"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -190,26 +190,42 @@ files = [
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
django = ">=4.2"
|
django = ">=4.2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "django-environ"
|
||||||
|
version = "0.11.2"
|
||||||
|
description = "A package that allows you to utilize 12factor inspired environment variables to configure your Django application."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6,<4"
|
||||||
|
files = [
|
||||||
|
{file = "django-environ-0.11.2.tar.gz", hash = "sha256:f32a87aa0899894c27d4e1776fa6b477e8164ed7f6b3e410a62a6d72caaf64be"},
|
||||||
|
{file = "django_environ-0.11.2-py2.py3-none-any.whl", hash = "sha256:0ff95ab4344bfeff693836aa978e6840abef2e2f1145adff7735892711590c05"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
develop = ["coverage[toml] (>=5.0a4)", "furo (>=2021.8.17b43,<2021.9.dev0)", "pytest (>=4.6.11)", "sphinx (>=3.5.0)", "sphinx-notfound-page"]
|
||||||
|
docs = ["furo (>=2021.8.17b43,<2021.9.dev0)", "sphinx (>=3.5.0)", "sphinx-notfound-page"]
|
||||||
|
testing = ["coverage[toml] (>=5.0a4)", "pytest (>=4.6.11)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.6"
|
version = "3.7"
|
||||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
{file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
|
{file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
|
||||||
{file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
|
{file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "requests"
|
name = "requests"
|
||||||
version = "2.31.0"
|
version = "2.32.3"
|
||||||
description = "Python HTTP for Humans."
|
description = "Python HTTP for Humans."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
|
||||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
@ -224,48 +240,48 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlparse"
|
name = "sqlparse"
|
||||||
version = "0.4.4"
|
version = "0.5.0"
|
||||||
description = "A non-validating SQL parser."
|
description = "A non-validating SQL parser."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
|
{file = "sqlparse-0.5.0-py3-none-any.whl", hash = "sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663"},
|
||||||
{file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
|
{file = "sqlparse-0.5.0.tar.gz", hash = "sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["build", "flake8"]
|
dev = ["build", "hatch"]
|
||||||
doc = ["sphinx"]
|
doc = ["sphinx"]
|
||||||
test = ["pytest", "pytest-cov"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tzdata"
|
name = "tzdata"
|
||||||
version = "2023.4"
|
version = "2024.1"
|
||||||
description = "Provider of IANA time zone data"
|
description = "Provider of IANA time zone data"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2"
|
python-versions = ">=2"
|
||||||
files = [
|
files = [
|
||||||
{file = "tzdata-2023.4-py2.py3-none-any.whl", hash = "sha256:aa3ace4329eeacda5b7beb7ea08ece826c28d761cda36e747cfbf97996d39bf3"},
|
{file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"},
|
||||||
{file = "tzdata-2023.4.tar.gz", hash = "sha256:dd54c94f294765522c77399649b4fefd95522479a664a0cec87f41bebc6148c9"},
|
{file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "2.1.0"
|
version = "2.2.1"
|
||||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
{file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
|
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
|
||||||
{file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
|
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||||
|
h2 = ["h2 (>=4,<5)"]
|
||||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||||
zstd = ["zstandard (>=0.18.0)"]
|
zstd = ["zstandard (>=0.18.0)"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "cf882708b341170fa02db4115bf2eeec4f2d0a97e468ab04136f4391ca1f9d20"
|
content-hash = "fc91f96209fbdf439cf9da459e6b98e3897b9672d0250bc97a7622a190006ff4"
|
||||||
|
|
|
@ -12,6 +12,7 @@ django = "^5.0"
|
||||||
crispy-bootstrap5 = "^2023.10"
|
crispy-bootstrap5 = "^2023.10"
|
||||||
django-crispy-forms = "^2.1"
|
django-crispy-forms = "^2.1"
|
||||||
ares-util = "^0.3.0"
|
ares-util = "^0.3.0"
|
||||||
|
django-environ = "^0.11.2"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|
|
@ -1,8 +1,24 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from . import models
|
from .models import Subject
|
||||||
|
from .models import SubjectData
|
||||||
|
|
||||||
|
|
||||||
@admin.register(models.Subject)
|
class SubjectDataInline(admin.TabularInline):
|
||||||
|
model = SubjectData
|
||||||
|
extra = 0 # is removes the extra empty forms
|
||||||
|
readonly_fields = [
|
||||||
|
'name',
|
||||||
|
'street',
|
||||||
|
'zip_code',
|
||||||
|
'city',
|
||||||
|
'city_part',
|
||||||
|
'created_date',
|
||||||
|
]
|
||||||
|
can_delete = False # Optional: Prevent deletion in the inline
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Subject)
|
||||||
class SubjectAdmin(admin.ModelAdmin):
|
class SubjectAdmin(admin.ModelAdmin):
|
||||||
list_display = ['id', 'name', 'city', 'city_part', 'zip_code']
|
list_display = ['id', 'vat_id']
|
||||||
|
inlines = [SubjectDataInline]
|
||||||
|
|
|
@ -8,6 +8,7 @@ from django.forms import fields
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
from accounts.models import User
|
||||||
|
|
||||||
|
|
||||||
class CreateSubjectForm(forms.Form):
|
class CreateSubjectForm(forms.Form):
|
||||||
|
@ -18,7 +19,9 @@ class CreateSubjectForm(forms.Form):
|
||||||
cin = fields.CharField(
|
cin = fields.CharField(
|
||||||
label=_('CIN'),
|
label=_('CIN'),
|
||||||
max_length=8,
|
max_length=8,
|
||||||
help_text=_('Enter the subject CIN, rest will be generated automatically'),
|
help_text=_(
|
||||||
|
'Enter the subject CIN, rest will be generated automatically',
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -41,3 +44,23 @@ class CreateSubjectForm(forms.Form):
|
||||||
return cin
|
return cin
|
||||||
|
|
||||||
raise ValidationError(self.error_messages['already_existing'])
|
raise ValidationError(self.error_messages['already_existing'])
|
||||||
|
|
||||||
|
|
||||||
|
class SelectSubjectForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ('supplier',)
|
||||||
|
labels = {'supplier': _('Current supplier')}
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self._user = kwargs.pop('current_user', None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.fields["supplier"].queryset = models.Subject.objects.exclude(
|
||||||
|
id__in=self._user.get_customers(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.helper = helper.FormHelper()
|
||||||
|
self.helper.form_action = 'subjects:list'
|
||||||
|
self.helper.form_method = 'post'
|
||||||
|
self.helper.add_input(layout.Submit('submit', _('Save')))
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
'vat_id',
|
'vat_id',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=12, null=True, verbose_name='vat_id'
|
blank=True, max_length=12, null=True, verbose_name='vat_id',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
('street', models.CharField(max_length=64, verbose_name='street')),
|
('street', models.CharField(max_length=64, verbose_name='street')),
|
||||||
|
@ -34,7 +34,7 @@ class Migration(migrations.Migration):
|
||||||
(
|
(
|
||||||
'city_part',
|
'city_part',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=64, null=True, verbose_name='city_part'
|
blank=True, max_length=64, null=True, verbose_name='city_part',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -18,14 +18,14 @@ class Migration(migrations.Migration):
|
||||||
model_name='subject',
|
model_name='subject',
|
||||||
name='city_part',
|
name='city_part',
|
||||||
field=models.CharField(
|
field=models.CharField(
|
||||||
blank=True, max_length=64, null=True, verbose_name='City part'
|
blank=True, max_length=64, null=True, verbose_name='City part',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='subject',
|
model_name='subject',
|
||||||
name='id',
|
name='id',
|
||||||
field=models.CharField(
|
field=models.CharField(
|
||||||
max_length=8, primary_key=True, serialize=False, verbose_name='CIN'
|
max_length=8, primary_key=True, serialize=False, verbose_name='CIN',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
|
@ -42,7 +42,7 @@ class Migration(migrations.Migration):
|
||||||
model_name='subject',
|
model_name='subject',
|
||||||
name='vat_id',
|
name='vat_id',
|
||||||
field=models.CharField(
|
field=models.CharField(
|
||||||
blank=True, max_length=12, null=True, verbose_name='VAT ID'
|
blank=True, max_length=12, null=True, verbose_name='VAT ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
|
|
|
@ -10,6 +10,9 @@ class Migration(migrations.Migration):
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
name='subject',
|
name='subject',
|
||||||
options={'verbose_name': 'Subject', 'verbose_name_plural': 'Subjects'},
|
options={
|
||||||
|
'verbose_name': 'Subject',
|
||||||
|
'verbose_name_plural': 'Subjects',
|
||||||
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
# Generated by Django 5.0.4 on 2024-06-14 20:08
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('subjects', '0003_alter_subject_options'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subject',
|
||||||
|
name='city',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subject',
|
||||||
|
name='city_part',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subject',
|
||||||
|
name='name',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subject',
|
||||||
|
name='street',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='subject',
|
||||||
|
name='zip_code',
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='SubjectData',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='ID',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('name', models.CharField(max_length=128, verbose_name='Name')),
|
||||||
|
('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',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'created_date',
|
||||||
|
models.DateTimeField(
|
||||||
|
auto_now_add=True, verbose_name='Created date',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'subject',
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to='subjects.subject',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Subject Data',
|
||||||
|
'verbose_name_plural': 'Subject Datas',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
23
subjects/migrations/0005_alter_subjectdata_subject.py
Normal file
23
subjects/migrations/0005_alter_subjectdata_subject.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Generated by Django 5.0.6 on 2024-07-04 21:59
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("subjects", "0004_remove_subject_city_remove_subject_city_part_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="subjectdata",
|
||||||
|
name="subject",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="subject_data",
|
||||||
|
to="subjects.subject",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -8,30 +8,35 @@ class Subject(models.Model):
|
||||||
verbose_name_plural = _('Subjects')
|
verbose_name_plural = _('Subjects')
|
||||||
|
|
||||||
id = models.CharField(_('CIN'), max_length=8, primary_key=True)
|
id = models.CharField(_('CIN'), max_length=8, primary_key=True)
|
||||||
|
vat_id = models.CharField(
|
||||||
name = models.CharField(_('Name'), max_length=128)
|
_('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'),
|
|
||||||
max_length=64,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
zip_code = models.CharField(
|
def get_latest_data(self):
|
||||||
_('Zip Code'),
|
return self.subject_data.filter(subject=self).order_by(
|
||||||
max_length=6,
|
'-created_date',
|
||||||
)
|
).first()
|
||||||
|
|
||||||
city = models.CharField(
|
|
||||||
_('City'),
|
|
||||||
max_length=64,
|
|
||||||
)
|
|
||||||
|
|
||||||
city_part = models.CharField(_('City part'), max_length=64, null=True, blank=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return f'{self.id} - {self.get_latest_data().name}'
|
||||||
|
|
||||||
def get_linked_users(self) -> list[int]:
|
|
||||||
return list(self.user_set.values_list('id', flat=True))
|
class SubjectData(models.Model):
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Subject Data')
|
||||||
|
verbose_name_plural = _('Subject Datas')
|
||||||
|
|
||||||
|
subject = models.ForeignKey(
|
||||||
|
Subject, on_delete=models.CASCADE, related_name='subject_data',
|
||||||
|
)
|
||||||
|
name = models.CharField(_('Name'), max_length=128)
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
created_date = models.DateTimeField(_('Created date'), auto_now_add=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.subject.id} - {self.name} - {self.created_date}'
|
||||||
|
|
|
@ -1,47 +1,87 @@
|
||||||
{% extends "facturio/base.html" %}
|
{% extends "facturio/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% load crispy_forms_tags %}
|
||||||
|
|
||||||
{% block title %}{% trans "Subjects" %}{% endblock %}
|
{% block title %}{% trans "Subjects" %}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<a href="{% url "subjects:create" %}" class="btn btn-primary" role="button">{% trans "Add new" %}</a>
|
{% with customers=request.user.get_customers %}
|
||||||
<table class="table">
|
{% crispy form form.helper %}
|
||||||
<thead>
|
<h2>{% trans "Customers" %}</h2>
|
||||||
<tr>
|
<table class="table">
|
||||||
<th>{% trans "CIN" %}</th>
|
<thead>
|
||||||
<th>{% trans "Name" %}</th>
|
<tr>
|
||||||
<th>{% trans "VAT ID" %}</th>
|
<th class="col-1">{% trans "CIN" %}</th>
|
||||||
<th>{% trans "Street" %}</th>
|
<th class="col-1">{% trans "VAT ID" %}</th>
|
||||||
<th>{% trans "Zip Code" %}</th>
|
<th class="col-2">{% trans "Name" %}</th>
|
||||||
<th>{% trans "City" %}</th>
|
<th class="col-1">{% trans "City" %}</th>
|
||||||
<th>{% trans "City part" %}</th>
|
<th class="col-2">{% trans "City part" %}</th>
|
||||||
<th>{% trans "Connect" %}</th>
|
<th class="col-2">{% trans "Street" %}</th>
|
||||||
</tr>
|
<th class="col-1">{% trans "Zip Code" %}</th>
|
||||||
</thead>
|
<th class="col-1">{% trans "Customers" %}</th>
|
||||||
<tbody>
|
</tr>
|
||||||
{% for subject in subjects %}
|
</thead>
|
||||||
{# FIXME: in the future, or when this create problems, find a better way#}
|
<tbody>
|
||||||
{% with linked_users=subject.get_linked_users %}
|
{% for subject in subjects %}
|
||||||
<tr>
|
{% if subject.id in customers %}
|
||||||
<td>{{ subject.id }}</td>
|
{% with subject_data=subject.get_latest_data %}
|
||||||
<td>{{ subject.name }}</td>
|
<tr>
|
||||||
<td>{{ subject.vat_id|default:_("None")}}</td>
|
<td>{{ subject.id }}</td>
|
||||||
<td>{{ subject.street }}</td>
|
<td>{{ subject.vat_id|default:_("None") }}</td>
|
||||||
<td>{{ subject.zip_code }}</td>
|
<td>{{ subject_data.name }}</td>
|
||||||
<td>{{ subject.city }}</td>
|
<td>{{ subject_data.city }}</td>
|
||||||
<td>{{ subject.city_part }}</td>
|
<td>{{ subject_data.city_part }}</td>
|
||||||
<td>
|
<td>{{ subject_data.street }}</td>
|
||||||
{% if request.user.id not in linked_users %}
|
<td>{{ subject_data.zip_code }}</td>
|
||||||
<a href="{% url "subjects:link" subject_id=subject.id %}" class="btn btn-primary"
|
<td>
|
||||||
role="button">{% trans "Link" %}</a>
|
<a href="{% url "subjects:unlink" subject_id=subject.id %}"
|
||||||
{% else %}
|
class="btn btn-secondary"
|
||||||
<a href="{% url "subjects:unlink" subject_id=subject.id %}" class="btn btn-danger"
|
role="button">{% trans "Cancel" %}</a>
|
||||||
role="button">{% trans "Unlink" %}</a>
|
</td>
|
||||||
{% endif %}
|
</tr>
|
||||||
</td>
|
{% endwith %}
|
||||||
</tr>
|
{% endif %}
|
||||||
{% endwith %}
|
{% endfor %}
|
||||||
{% endfor %}
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
<h2>{% trans "Others" %}</h2>
|
||||||
|
<a href="{% url "subjects:create" %}" class="btn btn-primary" role="button">{% trans "Add new" %}</a>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-1">{% trans "CIN" %}</th>
|
||||||
|
<th class="col-1">{% trans "VAT ID" %}</th>
|
||||||
|
<th class="col-2">{% trans "Name" %}</th>
|
||||||
|
<th class="col-1">{% trans "City" %}</th>
|
||||||
|
<th class="col-2">{% trans "City part" %}</th>
|
||||||
|
<th class="col-2">{% trans "Street" %}</th>
|
||||||
|
<th class="col-1">{% trans "Zip Code" %}</th>
|
||||||
|
<th class="col-1">{% trans "Customers" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for subject in subjects %}
|
||||||
|
{% if subject.id not in customers %}
|
||||||
|
{% with subject_data=subject.get_latest_data %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ subject.id }}</td>
|
||||||
|
<td>{{ subject.vat_id|default:_("None") }}</td>
|
||||||
|
<td>{{ subject_data.name }}</td>
|
||||||
|
<td>{{ subject_data.city }}</td>
|
||||||
|
<td>{{ subject_data.city_part }}</td>
|
||||||
|
<td>{{ subject_data.street }}</td>
|
||||||
|
<td>{{ subject_data.zip_code }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url "subjects:link" subject_id=subject.id %}"
|
||||||
|
class="btn btn-primary"
|
||||||
|
role="button">{% trans "Select" %}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endwith %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endwith %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -16,8 +16,28 @@ def build_address(street: str, zip_code: int | str, city: str, city_part: str) -
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def main_page(req: HttpRequest) -> HttpResponse:
|
def main_page(req: HttpRequest) -> HttpResponse:
|
||||||
subjects = models.Subject.objects.all()
|
if req.method == 'POST':
|
||||||
return render(req, 'subjects/index.html', dict(subjects=subjects))
|
select_subject_form = forms.SelectSubjectForm(
|
||||||
|
data=req.POST, instance=req.user, current_user=req.user,
|
||||||
|
)
|
||||||
|
if select_subject_form.is_valid():
|
||||||
|
select_subject_form.save()
|
||||||
|
return redirect(reverse('subjects:list'))
|
||||||
|
|
||||||
|
elif req.method == 'GET':
|
||||||
|
subjects = models.Subject.objects.exclude(
|
||||||
|
id=req.user.supplier.id if req.user.supplier else None,
|
||||||
|
)
|
||||||
|
select_subject_form = forms.SelectSubjectForm(
|
||||||
|
instance=req.user, current_user=req.user,
|
||||||
|
)
|
||||||
|
return render(
|
||||||
|
req,
|
||||||
|
'subjects/index.html',
|
||||||
|
dict(subjects=subjects, form=select_subject_form),
|
||||||
|
)
|
||||||
|
|
||||||
|
return HttpResponse(status=405)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -33,9 +53,11 @@ def create_subject(req: HttpRequest) -> HttpResponse:
|
||||||
ares_address_data = ares_data['address']
|
ares_address_data = ares_data['address']
|
||||||
ares_legal_data = ares_data['legal']
|
ares_legal_data = ares_data['legal']
|
||||||
|
|
||||||
models.Subject.objects.create(
|
subject = models.Subject.objects.create(
|
||||||
id=ares_legal_data['company_id'],
|
id=ares_legal_data['company_id'], vat_id=ares_legal_data['company_vat_id'],
|
||||||
vat_id=ares_legal_data['company_vat_id'],
|
)
|
||||||
|
models.SubjectData.objects.create(
|
||||||
|
subject=subject,
|
||||||
name=ares_legal_data['company_name'],
|
name=ares_legal_data['company_name'],
|
||||||
street=ares_address_data['street'],
|
street=ares_address_data['street'],
|
||||||
zip_code=ares_address_data['zip_code'],
|
zip_code=ares_address_data['zip_code'],
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<title>Facturio - {% block title %}{% trans "App" %}{% endblock %}</title>
|
<title>Facturio - {% block title %}{% trans "App" %}{% endblock %}</title>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||||
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
|
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
|
||||||
|
@ -19,14 +20,12 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{% url "subjects:list" %}">{% trans "Subjects" %}</a>
|
<a class="nav-link" href="{% url "subjects:list" %}">{% trans "Subjects" %}</a>
|
||||||
</li>
|
</li>
|
||||||
{#<li class="nav-item">#}
|
<li class="nav-item">
|
||||||
{# <a class="nav-link" href="#">Item 2</a>#}
|
<a class="nav-link" href="{% url "invoices:index" %}">{% trans "Invoices" %}</a>
|
||||||
{#</li>#}
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<div class="collapse navbar-collapse justify-content-end">
|
<div class="collapse navbar-collapse justify-content-end">
|
||||||
<ul class="navbar-nav">
|
<ul class="navbar-nav">
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: var(--font-family);
|
font-family: var(--font-family), sans-serif;
|
||||||
margin: 20px;
|
margin: 20px;
|
||||||
color: var(--main-color);
|
color: var(--main-color);
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
|
@ -160,7 +160,7 @@
|
||||||
<table id="invoice">
|
<table id="invoice">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="small-col">#</th>
|
<th class="small-col">Počet</th>
|
||||||
<th class="small-col">Jednotka</th>
|
<th class="small-col">Jednotka</th>
|
||||||
<th class="big-col">Popis položky</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">Cena za MJ</th>
|
||||||
|
|
Reference in a new issue