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/pre-commit/mirrors-autopep8 | ||||||
|  |     rev: v2.0.4 | ||||||
|  |     hooks: | ||||||
|  |     -   id: autopep8 | ||||||
|  | -   repo: https://github.com/asottile/add-trailing-comma | ||||||
|  |     rev: v3.1.0 | ||||||
|  |     hooks: | ||||||
|  |     -   id: add-trailing-comma | ||||||
| -   repo: https://github.com/asottile/reorder-python-imports | -   repo: https://github.com/asottile/reorder-python-imports | ||||||
|     rev: v3.12.0 |     rev: v3.13.0 | ||||||
|     hooks: |     hooks: | ||||||
|     -   id: reorder-python-imports |     -   id: reorder-python-imports | ||||||
| -   repo: https://github.com/astral-sh/ruff-pre-commit | -   repo: https://github.com/astral-sh/ruff-pre-commit | ||||||
|     rev: v0.2.0 |     rev: v0.5.5 | ||||||
|     hooks: |     hooks: | ||||||
|     -   id: ruff |     -   id: ruff | ||||||
|         args: [--fix, --exit-non-zero-on-fix] |         args: [--fix, --exit-non-zero-on-fix] | ||||||
|       - id: ruff-format |  | ||||||
|  |  | ||||||
							
								
								
									
										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 %} | ||||||
|  |         {% crispy form form.helper %} | ||||||
|  |         <h2>{% trans "Customers" %}</h2> | ||||||
|         <table class="table"> |         <table class="table"> | ||||||
|             <thead> |             <thead> | ||||||
|             <tr> |             <tr> | ||||||
|             <th>{% trans "CIN" %}</th> |                 <th class="col-1">{% trans "CIN" %}</th> | ||||||
|             <th>{% trans "Name" %}</th> |                 <th class="col-1">{% trans "VAT ID" %}</th> | ||||||
|             <th>{% trans "VAT ID" %}</th> |                 <th class="col-2">{% trans "Name" %}</th> | ||||||
|             <th>{% trans "Street" %}</th> |                 <th class="col-1">{% trans "City" %}</th> | ||||||
|             <th>{% trans "Zip Code" %}</th> |                 <th class="col-2">{% trans "City part" %}</th> | ||||||
|             <th>{% trans "City" %}</th> |                 <th class="col-2">{% trans "Street" %}</th> | ||||||
|             <th>{% trans "City part" %}</th> |                 <th class="col-1">{% trans "Zip Code" %}</th> | ||||||
|             <th>{% trans "Connect" %}</th> |                 <th class="col-1">{% trans "Customers" %}</th> | ||||||
|             </tr> |             </tr> | ||||||
|             </thead> |             </thead> | ||||||
|             <tbody> |             <tbody> | ||||||
|             {% for subject in subjects %} |             {% for subject in subjects %} | ||||||
|             {# FIXME: in the future, or when this create problems, find a better way#} |                 {% if subject.id in customers %} | ||||||
|             {% with linked_users=subject.get_linked_users %} |                     {% with subject_data=subject.get_latest_data %} | ||||||
|                         <tr> |                         <tr> | ||||||
|                             <td>{{ subject.id }}</td> |                             <td>{{ subject.id }}</td> | ||||||
|                     <td>{{ subject.name }}</td> |  | ||||||
|                             <td>{{ subject.vat_id|default:_("None") }}</td> |                             <td>{{ subject.vat_id|default:_("None") }}</td> | ||||||
|                     <td>{{ subject.street }}</td> |                             <td>{{ subject_data.name }}</td> | ||||||
|                     <td>{{ subject.zip_code }}</td> |                             <td>{{ subject_data.city }}</td> | ||||||
|                     <td>{{ subject.city }}</td> |                             <td>{{ subject_data.city_part }}</td> | ||||||
|                     <td>{{ subject.city_part }}</td> |                             <td>{{ subject_data.street }}</td> | ||||||
|  |                             <td>{{ subject_data.zip_code }}</td> | ||||||
|                             <td> |                             <td> | ||||||
|                         {% if request.user.id not in linked_users %} |                                 <a href="{% url "subjects:unlink" subject_id=subject.id %}" | ||||||
|                             <a href="{% url "subjects:link" subject_id=subject.id %}" class="btn btn-primary" |                                    class="btn btn-secondary" | ||||||
|                                role="button">{% trans "Link" %}</a> |                                    role="button">{% trans "Cancel" %}</a> | ||||||
|                         {% else %} |  | ||||||
|                             <a href="{% url "subjects:unlink" subject_id=subject.id %}" class="btn btn-danger" |  | ||||||
|                                role="button">{% trans "Unlink" %}</a> |  | ||||||
|                         {% endif %} |  | ||||||
|                             </td> |                             </td> | ||||||
|                         </tr> |                         </tr> | ||||||
|                     {% endwith %} |                     {% endwith %} | ||||||
|  |                 {% endif %} | ||||||
|             {% 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