Spaces:
Running
Running
sachin
commited on
Commit
·
5538ec7
1
Parent(s):
5a68da9
taxTech
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- Dockerfile +1 -3
- dashboard/__init__.py +0 -0
- dashboard/admin.py +7 -0
- dashboard/apps.py +6 -0
- dashboard/commands/generate_companies.py +32 -0
- dashboard/commands/load_coordinates.py +26 -0
- dashboard/commands/populate_country_data.py +47 -0
- dashboard/management/commands/generate_companies.py +32 -0
- dashboard/management/commands/load_coordinates.py +26 -0
- dashboard/management/commands/populate_country_data.py +47 -0
- dashboard/migrations/0001_initial.py +27 -0
- dashboard/migrations/0002_remove_country_effective_tax_rate_remove_country_gdp_and_more.py +46 -0
- dashboard/migrations/0003_countrydata_questionnaire.py +39 -0
- dashboard/migrations/0004_alter_countrydata_balance_sheet_and_more.py +38 -0
- dashboard/migrations/__init__.py +0 -0
- dashboard/models.py +43 -0
- dashboard/static/css/style.css +137 -0
- dashboard/static/js/map.js +71 -0
- dashboard/templates/dashboard/aiAgent.html +10 -0
- dashboard/templates/dashboard/company_detail.html +34 -0
- dashboard/templates/dashboard/connectors.html +10 -0
- dashboard/templates/dashboard/country_detail.html +105 -0
- dashboard/templates/dashboard/country_list.html +41 -0
- dashboard/templates/dashboard/dashboard.html +267 -0
- dashboard/templates/dashboard/masterData.html +10 -0
- dashboard/templates/dashboard/start_page.html +61 -0
- dashboard/templates/dashboard/userManagement.html +10 -0
- dashboard/tests.py +3 -0
- dashboard/urls.py +24 -0
- dashboard/views.py +82 -0
- docs/setup.md +0 -47
- games/__init__.py +0 -0
- games/admin.py +4 -0
- games/apps.py +6 -0
- games/migrations/0001_initial.py +23 -0
- games/migrations/__init__.py +0 -0
- games/models.py +6 -0
- games/templates/game_list.html +16 -0
- games/tests.py +3 -0
- games/urls.py +6 -0
- games/views.py +6 -0
- inference/__init__.py +0 -0
- inference/admin.py +3 -0
- inference/apps.py +6 -0
- inference/migrations/__init__.py +0 -0
- inference/models.py +3 -0
- inference/tests.py +3 -0
- inference/urls.py +15 -0
- inference/views.py +430 -0
- recipes/urls.py +0 -11
Dockerfile
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
# pull official base image
|
2 |
-
FROM python:3.
|
3 |
-
|
4 |
RUN useradd -m -u 1000 user
|
5 |
USER user
|
6 |
|
@@ -26,7 +25,6 @@ RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
|
26 |
COPY --chown=user . /app
|
27 |
|
28 |
RUN python manage.py migrate
|
29 |
-
|
30 |
CMD ["python", "manage.py", "runserver", "0.0.0.0:7860"]
|
31 |
|
32 |
#CMD ["uvicorn", "spaces.asgi:application", "--host", "0.0.0.0", "--port", "7860"]
|
|
|
1 |
# pull official base image
|
2 |
+
FROM python:3.12-bullseye
|
|
|
3 |
RUN useradd -m -u 1000 user
|
4 |
USER user
|
5 |
|
|
|
25 |
COPY --chown=user . /app
|
26 |
|
27 |
RUN python manage.py migrate
|
|
|
28 |
CMD ["python", "manage.py", "runserver", "0.0.0.0:7860"]
|
29 |
|
30 |
#CMD ["uvicorn", "spaces.asgi:application", "--host", "0.0.0.0", "--port", "7860"]
|
dashboard/__init__.py
ADDED
File without changes
|
dashboard/admin.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.contrib import admin
|
2 |
+
|
3 |
+
# Register your models here.
|
4 |
+
from django.contrib import admin
|
5 |
+
from .models import Country
|
6 |
+
|
7 |
+
admin.site.register(Country)
|
dashboard/apps.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.apps import AppConfig
|
2 |
+
|
3 |
+
|
4 |
+
class DashboardConfig(AppConfig):
|
5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
6 |
+
name = 'dashboard'
|
dashboard/commands/generate_companies.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import random
|
2 |
+
from django.core.management.base import BaseCommand
|
3 |
+
from dashboard.models import Country, Company
|
4 |
+
|
5 |
+
|
6 |
+
class Command(BaseCommand):
|
7 |
+
help = "Generate random companies for all countries"
|
8 |
+
|
9 |
+
def handle(self, *args, **kwargs):
|
10 |
+
company_names = [
|
11 |
+
"Global Tech Inc.", "Alpha Industries", "Beta Solutions", "Delta Corp.",
|
12 |
+
"Zeta Enterprises", "Omega Systems", "Apollo Holdings", "Titan Innovations"
|
13 |
+
]
|
14 |
+
|
15 |
+
for country in Country.objects.all():
|
16 |
+
self.stdout.write(f"Generating companies for {country.name}...")
|
17 |
+
for _ in range(random.randint(3, 6)): # Generate 3-6 companies per country
|
18 |
+
Company.objects.create(
|
19 |
+
name=random.choice(company_names),
|
20 |
+
country=country,
|
21 |
+
balance_sheet={
|
22 |
+
"Aktiva": {
|
23 |
+
"Anlagevermögen": random.randint(100000, 500000),
|
24 |
+
"Umlaufvermögen": random.randint(50000, 200000)
|
25 |
+
},
|
26 |
+
"Passiva": {
|
27 |
+
"Eigenkapital": random.randint(70000, 300000),
|
28 |
+
"Fremdkapital": random.randint(20000, 150000)
|
29 |
+
}
|
30 |
+
}
|
31 |
+
)
|
32 |
+
self.stdout.write(self.style.SUCCESS("Companies successfully generated!"))
|
dashboard/commands/load_coordinates.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from django.core.management.base import BaseCommand
|
3 |
+
from dashboard.models import Country
|
4 |
+
|
5 |
+
class Command(BaseCommand):
|
6 |
+
help = "Load country data into the database"
|
7 |
+
|
8 |
+
def handle(self, *args, **kwargs):
|
9 |
+
data = [
|
10 |
+
{"name": "Germany", "iso_code": "DE", "latitude": 51.1657, "longitude": 10.4515, "pillar2_implemented": True, "local_top_up_tax": True},
|
11 |
+
{"name": "France", "iso_code": "FR", "latitude": 46.6034, "longitude": 1.8883, "pillar2_implemented": True, "local_top_up_tax": False},
|
12 |
+
{"name": "United States", "iso_code": "US", "latitude": 37.0902, "longitude": -95.7129, "pillar2_implemented": False, "local_top_up_tax": False},
|
13 |
+
{"name": "Japan", "iso_code": "JP", "latitude": 36.2048, "longitude": 138.2529, "pillar2_implemented": True, "local_top_up_tax": True},
|
14 |
+
{"name": "India", "iso_code": "IN", "latitude": 20.5937, "longitude": 78.9629, "pillar2_implemented": False, "local_top_up_tax": False}
|
15 |
+
]
|
16 |
+
|
17 |
+
for country_data in data:
|
18 |
+
country, created = Country.objects.get_or_create(
|
19 |
+
name=country_data["name"],
|
20 |
+
iso_code=country_data["iso_code"],
|
21 |
+
latitude=country_data["latitude"],
|
22 |
+
longitude=country_data["longitude"],
|
23 |
+
pillar2_implemented=country_data["pillar2_implemented"],
|
24 |
+
local_top_up_tax=country_data["local_top_up_tax"]
|
25 |
+
)
|
26 |
+
self.stdout.write(f"{'Created' if created else 'Updated'}: {country.name}")
|
dashboard/commands/populate_country_data.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.core.management.base import BaseCommand
|
2 |
+
from dashboard.models import Country, CountryData
|
3 |
+
import random
|
4 |
+
|
5 |
+
class Command(BaseCommand):
|
6 |
+
help = 'Populate CountryData with random balance sheet values'
|
7 |
+
|
8 |
+
def handle(self, *args, **kwargs):
|
9 |
+
countries = Country.objects.all()
|
10 |
+
for country in countries:
|
11 |
+
for year in range(2020, 2025): # Add data for multiple years
|
12 |
+
balance_sheet = {
|
13 |
+
"Aktiva": {
|
14 |
+
"Anlagevermögen": {
|
15 |
+
"Sachanlagen": random.randint(10000, 50000),
|
16 |
+
"immaterielle Vermögensgegenstände": random.randint(5000, 20000),
|
17 |
+
"Finanzanlagen": random.randint(20000, 70000),
|
18 |
+
},
|
19 |
+
"Umlaufvermögen": {
|
20 |
+
"Vorräte": random.randint(3000, 15000),
|
21 |
+
"Forderungen": random.randint(5000, 25000),
|
22 |
+
"Kassenbestand": random.randint(1000, 5000),
|
23 |
+
"Wertpapiere": random.randint(10000, 20000),
|
24 |
+
}
|
25 |
+
},
|
26 |
+
"Passiva": {
|
27 |
+
"Eigenkapital": {
|
28 |
+
"Gezeichnetes Kapital": random.randint(50000, 100000),
|
29 |
+
"Kapitalrücklagen": random.randint(10000, 50000),
|
30 |
+
"Gewinnrücklagen": random.randint(20000, 60000),
|
31 |
+
},
|
32 |
+
"Fremdkapital": {
|
33 |
+
"Kurzfristige Verbindlichkeiten": random.randint(10000, 40000),
|
34 |
+
"langfristige Verbindlichkeiten": random.randint(30000, 80000),
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
CountryData.objects.create(
|
40 |
+
country=country,
|
41 |
+
year=year,
|
42 |
+
balance_sheet=balance_sheet,
|
43 |
+
company_name=f"Example Company {year}",
|
44 |
+
is_plausible=random.choice([True, False])
|
45 |
+
)
|
46 |
+
|
47 |
+
self.stdout.write(self.style.SUCCESS("Successfully populated CountryData"))
|
dashboard/management/commands/generate_companies.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import random
|
2 |
+
from django.core.management.base import BaseCommand
|
3 |
+
from dashboard.models import Country, Company
|
4 |
+
|
5 |
+
|
6 |
+
class Command(BaseCommand):
|
7 |
+
help = "Generate random companies for all countries"
|
8 |
+
|
9 |
+
def handle(self, *args, **kwargs):
|
10 |
+
company_names = [
|
11 |
+
"Global Tech Inc.", "Alpha Industries", "Beta Solutions", "Delta Corp.",
|
12 |
+
"Zeta Enterprises", "Omega Systems", "Apollo Holdings", "Titan Innovations"
|
13 |
+
]
|
14 |
+
|
15 |
+
for country in Country.objects.all():
|
16 |
+
self.stdout.write(f"Generating companies for {country.name}...")
|
17 |
+
for _ in range(random.randint(3, 6)): # Generate 3-6 companies per country
|
18 |
+
Company.objects.create(
|
19 |
+
name=random.choice(company_names),
|
20 |
+
country=country,
|
21 |
+
balance_sheet={
|
22 |
+
"Aktiva": {
|
23 |
+
"Anlagevermögen": random.randint(100000, 500000),
|
24 |
+
"Umlaufvermögen": random.randint(50000, 200000)
|
25 |
+
},
|
26 |
+
"Passiva": {
|
27 |
+
"Eigenkapital": random.randint(70000, 300000),
|
28 |
+
"Fremdkapital": random.randint(20000, 150000)
|
29 |
+
}
|
30 |
+
}
|
31 |
+
)
|
32 |
+
self.stdout.write(self.style.SUCCESS("Companies successfully generated!"))
|
dashboard/management/commands/load_coordinates.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from django.core.management.base import BaseCommand
|
3 |
+
from dashboard.models import Country
|
4 |
+
|
5 |
+
class Command(BaseCommand):
|
6 |
+
help = "Load country data into the database"
|
7 |
+
|
8 |
+
def handle(self, *args, **kwargs):
|
9 |
+
data = [
|
10 |
+
{"name": "Germany", "iso_code": "DE", "latitude": 51.1657, "longitude": 10.4515, "pillar2_implemented": True, "local_top_up_tax": True},
|
11 |
+
{"name": "France", "iso_code": "FR", "latitude": 46.6034, "longitude": 1.8883, "pillar2_implemented": True, "local_top_up_tax": False},
|
12 |
+
{"name": "United States", "iso_code": "US", "latitude": 37.0902, "longitude": -95.7129, "pillar2_implemented": False, "local_top_up_tax": False},
|
13 |
+
{"name": "Japan", "iso_code": "JP", "latitude": 36.2048, "longitude": 138.2529, "pillar2_implemented": True, "local_top_up_tax": True},
|
14 |
+
{"name": "India", "iso_code": "IN", "latitude": 20.5937, "longitude": 78.9629, "pillar2_implemented": False, "local_top_up_tax": False}
|
15 |
+
]
|
16 |
+
|
17 |
+
for country_data in data:
|
18 |
+
country, created = Country.objects.get_or_create(
|
19 |
+
name=country_data["name"],
|
20 |
+
iso_code=country_data["iso_code"],
|
21 |
+
latitude=country_data["latitude"],
|
22 |
+
longitude=country_data["longitude"],
|
23 |
+
pillar2_implemented=country_data["pillar2_implemented"],
|
24 |
+
local_top_up_tax=country_data["local_top_up_tax"]
|
25 |
+
)
|
26 |
+
self.stdout.write(f"{'Created' if created else 'Updated'}: {country.name}")
|
dashboard/management/commands/populate_country_data.py
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.core.management.base import BaseCommand
|
2 |
+
from dashboard.models import Country, CountryData
|
3 |
+
import random
|
4 |
+
|
5 |
+
class Command(BaseCommand):
|
6 |
+
help = 'Populate CountryData with random balance sheet values'
|
7 |
+
|
8 |
+
def handle(self, *args, **kwargs):
|
9 |
+
countries = Country.objects.all()
|
10 |
+
for country in countries:
|
11 |
+
for year in range(2020, 2025): # Add data for multiple years
|
12 |
+
balance_sheet = {
|
13 |
+
"Aktiva": {
|
14 |
+
"Anlagevermögen": {
|
15 |
+
"Sachanlagen": random.randint(10000, 50000),
|
16 |
+
"immaterielle Vermögensgegenstände": random.randint(5000, 20000),
|
17 |
+
"Finanzanlagen": random.randint(20000, 70000),
|
18 |
+
},
|
19 |
+
"Umlaufvermögen": {
|
20 |
+
"Vorräte": random.randint(3000, 15000),
|
21 |
+
"Forderungen": random.randint(5000, 25000),
|
22 |
+
"Kassenbestand": random.randint(1000, 5000),
|
23 |
+
"Wertpapiere": random.randint(10000, 20000),
|
24 |
+
}
|
25 |
+
},
|
26 |
+
"Passiva": {
|
27 |
+
"Eigenkapital": {
|
28 |
+
"Gezeichnetes Kapital": random.randint(50000, 100000),
|
29 |
+
"Kapitalrücklagen": random.randint(10000, 50000),
|
30 |
+
"Gewinnrücklagen": random.randint(20000, 60000),
|
31 |
+
},
|
32 |
+
"Fremdkapital": {
|
33 |
+
"Kurzfristige Verbindlichkeiten": random.randint(10000, 40000),
|
34 |
+
"langfristige Verbindlichkeiten": random.randint(30000, 80000),
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
CountryData.objects.create(
|
40 |
+
country=country,
|
41 |
+
year=year,
|
42 |
+
balance_sheet=balance_sheet,
|
43 |
+
company_name=f"Example Company {year}",
|
44 |
+
is_plausible=random.choice([True, False])
|
45 |
+
)
|
46 |
+
|
47 |
+
self.stdout.write(self.style.SUCCESS("Successfully populated CountryData"))
|
dashboard/migrations/0001_initial.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.3 on 2024-11-24 10:34
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
initial = True
|
9 |
+
|
10 |
+
dependencies = [
|
11 |
+
]
|
12 |
+
|
13 |
+
operations = [
|
14 |
+
migrations.CreateModel(
|
15 |
+
name='Country',
|
16 |
+
fields=[
|
17 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
18 |
+
('name', models.CharField(max_length=100)),
|
19 |
+
('iso_code', models.CharField(max_length=3, unique=True)),
|
20 |
+
('gdp', models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True)),
|
21 |
+
('effective_tax_rate', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)),
|
22 |
+
('part_of_pillar2', models.BooleanField(default=False)),
|
23 |
+
('latitude', models.FloatField(blank=True, null=True)),
|
24 |
+
('longitude', models.FloatField(blank=True, null=True)),
|
25 |
+
],
|
26 |
+
),
|
27 |
+
]
|
dashboard/migrations/0002_remove_country_effective_tax_rate_remove_country_gdp_and_more.py
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.3 on 2024-11-24 11:04
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
dependencies = [
|
9 |
+
('dashboard', '0001_initial'),
|
10 |
+
]
|
11 |
+
|
12 |
+
operations = [
|
13 |
+
migrations.RemoveField(
|
14 |
+
model_name='country',
|
15 |
+
name='effective_tax_rate',
|
16 |
+
),
|
17 |
+
migrations.RemoveField(
|
18 |
+
model_name='country',
|
19 |
+
name='gdp',
|
20 |
+
),
|
21 |
+
migrations.AddField(
|
22 |
+
model_name='country',
|
23 |
+
name='local_top_up_tax',
|
24 |
+
field=models.BooleanField(default=False),
|
25 |
+
),
|
26 |
+
migrations.AddField(
|
27 |
+
model_name='country',
|
28 |
+
name='pillar2_implemented',
|
29 |
+
field=models.BooleanField(default=False),
|
30 |
+
),
|
31 |
+
migrations.AlterField(
|
32 |
+
model_name='country',
|
33 |
+
name='iso_code',
|
34 |
+
field=models.CharField(max_length=10),
|
35 |
+
),
|
36 |
+
migrations.AlterField(
|
37 |
+
model_name='country',
|
38 |
+
name='latitude',
|
39 |
+
field=models.FloatField(),
|
40 |
+
),
|
41 |
+
migrations.AlterField(
|
42 |
+
model_name='country',
|
43 |
+
name='longitude',
|
44 |
+
field=models.FloatField(),
|
45 |
+
),
|
46 |
+
]
|
dashboard/migrations/0003_countrydata_questionnaire.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.3 on 2024-11-24 14:29
|
2 |
+
|
3 |
+
import django.db.models.deletion
|
4 |
+
from django.conf import settings
|
5 |
+
from django.db import migrations, models
|
6 |
+
|
7 |
+
|
8 |
+
class Migration(migrations.Migration):
|
9 |
+
|
10 |
+
dependencies = [
|
11 |
+
('dashboard', '0002_remove_country_effective_tax_rate_remove_country_gdp_and_more'),
|
12 |
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
13 |
+
]
|
14 |
+
|
15 |
+
operations = [
|
16 |
+
migrations.CreateModel(
|
17 |
+
name='CountryData',
|
18 |
+
fields=[
|
19 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
20 |
+
('year', models.IntegerField()),
|
21 |
+
('balance_sheet', models.TextField()),
|
22 |
+
('company_name', models.CharField(max_length=200)),
|
23 |
+
('is_plausible', models.BooleanField(default=True)),
|
24 |
+
('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='data', to='dashboard.country')),
|
25 |
+
],
|
26 |
+
),
|
27 |
+
migrations.CreateModel(
|
28 |
+
name='Questionnaire',
|
29 |
+
fields=[
|
30 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
31 |
+
('question', models.TextField()),
|
32 |
+
('response', models.TextField(blank=True, null=True)),
|
33 |
+
('created_at', models.DateTimeField(auto_now_add=True)),
|
34 |
+
('is_resolved', models.BooleanField(default=False)),
|
35 |
+
('country_data', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questionnaires', to='dashboard.countrydata')),
|
36 |
+
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
37 |
+
],
|
38 |
+
),
|
39 |
+
]
|
dashboard/migrations/0004_alter_countrydata_balance_sheet_and_more.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.3 on 2024-11-24 15:07
|
2 |
+
|
3 |
+
import django.db.models.deletion
|
4 |
+
from django.db import migrations, models
|
5 |
+
|
6 |
+
|
7 |
+
class Migration(migrations.Migration):
|
8 |
+
|
9 |
+
dependencies = [
|
10 |
+
('dashboard', '0003_countrydata_questionnaire'),
|
11 |
+
]
|
12 |
+
|
13 |
+
operations = [
|
14 |
+
migrations.AlterField(
|
15 |
+
model_name='countrydata',
|
16 |
+
name='balance_sheet',
|
17 |
+
field=models.JSONField(default=dict),
|
18 |
+
),
|
19 |
+
migrations.AlterField(
|
20 |
+
model_name='countrydata',
|
21 |
+
name='company_name',
|
22 |
+
field=models.CharField(max_length=255),
|
23 |
+
),
|
24 |
+
migrations.AlterField(
|
25 |
+
model_name='countrydata',
|
26 |
+
name='country',
|
27 |
+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dashboard.country'),
|
28 |
+
),
|
29 |
+
migrations.CreateModel(
|
30 |
+
name='Company',
|
31 |
+
fields=[
|
32 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
33 |
+
('name', models.CharField(max_length=200)),
|
34 |
+
('balance_sheet', models.JSONField()),
|
35 |
+
('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='companies', to='dashboard.country')),
|
36 |
+
],
|
37 |
+
),
|
38 |
+
]
|
dashboard/migrations/__init__.py
ADDED
File without changes
|
dashboard/models.py
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.contrib.auth.models import User
|
2 |
+
from django.db import models
|
3 |
+
|
4 |
+
class Country(models.Model):
|
5 |
+
name = models.CharField(max_length=100)
|
6 |
+
iso_code = models.CharField(max_length=10)
|
7 |
+
latitude = models.FloatField()
|
8 |
+
longitude = models.FloatField()
|
9 |
+
part_of_pillar2 = models.BooleanField(default=False)
|
10 |
+
pillar2_implemented = models.BooleanField(default=False) # Neu
|
11 |
+
local_top_up_tax = models.BooleanField(default=False) # Neu
|
12 |
+
|
13 |
+
def __str__(self):
|
14 |
+
return self.name
|
15 |
+
|
16 |
+
class CountryData(models.Model):
|
17 |
+
country = models.ForeignKey(Country, on_delete=models.CASCADE)
|
18 |
+
year = models.IntegerField()
|
19 |
+
balance_sheet = models.JSONField(default=dict) # JSONField for structured data
|
20 |
+
company_name = models.CharField(max_length=255)
|
21 |
+
is_plausible = models.BooleanField(default=True)
|
22 |
+
|
23 |
+
def __str__(self):
|
24 |
+
return f"{self.country.name} - {self.year}"
|
25 |
+
|
26 |
+
class Questionnaire(models.Model):
|
27 |
+
country_data = models.ForeignKey(CountryData, on_delete=models.CASCADE, related_name='questionnaires')
|
28 |
+
question = models.TextField()
|
29 |
+
response = models.TextField(blank=True, null=True)
|
30 |
+
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
|
31 |
+
created_at = models.DateTimeField(auto_now_add=True)
|
32 |
+
is_resolved = models.BooleanField(default=False)
|
33 |
+
|
34 |
+
def __str__(self):
|
35 |
+
return f"Questionnaire for {self.country_data.country.name} ({self.country_data.year})"
|
36 |
+
|
37 |
+
class Company(models.Model):
|
38 |
+
name = models.CharField(max_length=200)
|
39 |
+
country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='companies')
|
40 |
+
balance_sheet = models.JSONField() # JSONField to store Aktiva/Passiva data
|
41 |
+
|
42 |
+
def __str__(self):
|
43 |
+
return self.name
|
dashboard/static/css/style.css
ADDED
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* style.css */
|
2 |
+
* {
|
3 |
+
margin: 0;
|
4 |
+
padding: 0;
|
5 |
+
box-sizing: border-box;
|
6 |
+
}
|
7 |
+
|
8 |
+
body {
|
9 |
+
font-family: 'Roboto', sans-serif;
|
10 |
+
background-color: #f4f8ff; /* Helles Blau als Hintergrund */
|
11 |
+
color: #333;
|
12 |
+
}
|
13 |
+
|
14 |
+
.hero {
|
15 |
+
background-color: #007bb5; /* Blau-Ton für den Hero-Bereich */
|
16 |
+
color: white;
|
17 |
+
text-align: center;
|
18 |
+
padding: 100px 0;
|
19 |
+
border-bottom: 5px solid #006699; /* Dunklerer Blau-Ton als Trennung */
|
20 |
+
}
|
21 |
+
|
22 |
+
.hero h1 {
|
23 |
+
font-size: 3em;
|
24 |
+
margin-bottom: 20px;
|
25 |
+
}
|
26 |
+
|
27 |
+
.hero p {
|
28 |
+
font-size: 1.2em;
|
29 |
+
margin-bottom: 30px;
|
30 |
+
}
|
31 |
+
|
32 |
+
.cta-button {
|
33 |
+
background-color: #00aaff; /* Hellerer Blau-Ton für Button */
|
34 |
+
color: white;
|
35 |
+
padding: 10px 20px;
|
36 |
+
text-decoration: none;
|
37 |
+
font-size: 1.1em;
|
38 |
+
border-radius: 5px;
|
39 |
+
margin-top: 20px;
|
40 |
+
}
|
41 |
+
|
42 |
+
.cta-button:hover {
|
43 |
+
background-color: #0099cc; /* Dunklerer Blau-Ton für Hover */
|
44 |
+
}
|
45 |
+
|
46 |
+
.links {
|
47 |
+
margin-top: 30px;
|
48 |
+
}
|
49 |
+
|
50 |
+
.link-item {
|
51 |
+
color: #00aaff;
|
52 |
+
font-size: 1.1em;
|
53 |
+
text-decoration: none;
|
54 |
+
margin-right: 20px;
|
55 |
+
}
|
56 |
+
|
57 |
+
.link-item:hover {
|
58 |
+
text-decoration: underline;
|
59 |
+
}
|
60 |
+
|
61 |
+
.features {
|
62 |
+
padding: 50px 20px;
|
63 |
+
text-align: center;
|
64 |
+
background-color: #e1efff; /* Leichterer Blauton für Features-Sektion */
|
65 |
+
}
|
66 |
+
|
67 |
+
.features h2 {
|
68 |
+
font-size: 2.5em;
|
69 |
+
margin-bottom: 40px;
|
70 |
+
}
|
71 |
+
|
72 |
+
.feature {
|
73 |
+
background-color: white;
|
74 |
+
padding: 20px;
|
75 |
+
margin: 20px 0;
|
76 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
77 |
+
border-radius: 8px;
|
78 |
+
}
|
79 |
+
|
80 |
+
.feature h3 {
|
81 |
+
font-size: 1.5em;
|
82 |
+
margin-bottom: 10px;
|
83 |
+
}
|
84 |
+
|
85 |
+
.feature p {
|
86 |
+
font-size: 1em;
|
87 |
+
color: #555;
|
88 |
+
}
|
89 |
+
/* Configuration Section Styling */
|
90 |
+
.configuration {
|
91 |
+
background-color: #f4f8ff; /* Blau-Ton für den Hintergrund */
|
92 |
+
color: #333;
|
93 |
+
text-align: center; /* Den Text zentrieren, wenn es ein zentrierter Header sein soll */
|
94 |
+
padding: 80px 0; /* Etwas weniger Padding, damit mehr Platz für den Text bleibt */
|
95 |
+
border-bottom: 5px solid #006699; /* Dunklerer Blau-Ton als Trennung */
|
96 |
+
}
|
97 |
+
|
98 |
+
/* Container innerhalb der Section */
|
99 |
+
.configuration .container {
|
100 |
+
max-width: 1200px; /* Maximale Breite für die Container */
|
101 |
+
margin: 0 auto; /* Zentriert den Container */
|
102 |
+
padding: 0 15px; /* Leichter Abstand zu den Rändern */
|
103 |
+
}
|
104 |
+
|
105 |
+
/* Stil für die Überschrift */
|
106 |
+
.configuration h1 {
|
107 |
+
font-size: 3em; /* Größere Schriftgröße für den Titel */
|
108 |
+
margin-bottom: 20px; /* Abstand unter der Überschrift */
|
109 |
+
line-height: 1.2; /* Zeilenhöhe für bessere Lesbarkeit */
|
110 |
+
}
|
111 |
+
|
112 |
+
/* Stil für die CTA-Schaltfläche */
|
113 |
+
.cta-button {
|
114 |
+
background-color: #00aaff; /* Hellerer Blau-Ton für den Button */
|
115 |
+
color: white;
|
116 |
+
padding: 15px 30px; /* Mehr Padding für die Schaltfläche */
|
117 |
+
text-decoration: none;
|
118 |
+
font-size: 1.2em; /* Etwas größere Schriftgröße für bessere Sichtbarkeit */
|
119 |
+
border-radius: 5px;
|
120 |
+
margin-top: 20px;
|
121 |
+
display: inline-block; /* Der Button wird als Inline-Block angezeigt, damit er nicht die gesamte Zeile ausfüllt */
|
122 |
+
}
|
123 |
+
|
124 |
+
.cta-button:hover {
|
125 |
+
background-color: #0099cc; /* Dunklerer Blau-Ton für Hover-Effekt */
|
126 |
+
}
|
127 |
+
|
128 |
+
footer {
|
129 |
+
background-color: #007bb5; /* Gleicher Blau-Ton wie im Hero-Bereich */
|
130 |
+
color: white;
|
131 |
+
text-align: center;
|
132 |
+
padding: 20px;
|
133 |
+
}
|
134 |
+
|
135 |
+
footer p {
|
136 |
+
font-size: 1em;
|
137 |
+
}
|
dashboard/static/js/map.js
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*const countries = [
|
2 |
+
{
|
3 |
+
name: "Germany",
|
4 |
+
iso_code: "DE",
|
5 |
+
latitude: 51.1657,
|
6 |
+
longitude: 10.4515,
|
7 |
+
pillar2_implemented: true,
|
8 |
+
local_top_up_tax: true
|
9 |
+
},
|
10 |
+
{
|
11 |
+
name: "France",
|
12 |
+
iso_code: "FR",
|
13 |
+
latitude: 46.6034,
|
14 |
+
longitude: 1.8883,
|
15 |
+
pillar2_implemented: true,
|
16 |
+
local_top_up_tax: false
|
17 |
+
},
|
18 |
+
{
|
19 |
+
name: "United States",
|
20 |
+
iso_code: "US",
|
21 |
+
latitude: 37.0902,
|
22 |
+
longitude: -95.7129,
|
23 |
+
pillar2_implemented: false,
|
24 |
+
local_top_up_tax: false
|
25 |
+
},
|
26 |
+
{
|
27 |
+
name: "Japan",
|
28 |
+
iso_code: "JP",
|
29 |
+
latitude: 36.2048,
|
30 |
+
longitude: 138.2529,
|
31 |
+
pillar2_implemented: true,
|
32 |
+
local_top_up_tax: true
|
33 |
+
},
|
34 |
+
{
|
35 |
+
name: "India",
|
36 |
+
iso_code: "IN",
|
37 |
+
latitude: 20.5937,
|
38 |
+
longitude: 78.9629,
|
39 |
+
pillar2_implemented: false,
|
40 |
+
local_top_up_tax: false
|
41 |
+
}
|
42 |
+
];
|
43 |
+
*/
|
44 |
+
// Initialize map
|
45 |
+
const map = L.map('map').setView([20, 0], 2);
|
46 |
+
|
47 |
+
// Add OpenStreetMap tiles
|
48 |
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
49 |
+
maxZoom: 19
|
50 |
+
}).addTo(map);
|
51 |
+
|
52 |
+
// Add countries to map
|
53 |
+
countries.forEach(country => {
|
54 |
+
const color = country.pillar2_implemented ? 'green' : 'gray';
|
55 |
+
|
56 |
+
// Add circle marker for each country
|
57 |
+
L.circleMarker([country.latitude, country.longitude], {
|
58 |
+
color: color,
|
59 |
+
radius: 10
|
60 |
+
}).addTo(map).bindPopup(`${country.name}`);
|
61 |
+
|
62 |
+
// Add symbol for Local Top-Up Tax
|
63 |
+
if (country.local_top_up_tax) {
|
64 |
+
L.marker([country.latitude, country.longitude], {
|
65 |
+
icon: L.divIcon({
|
66 |
+
className: 'custom-icon',
|
67 |
+
html: '<span style="color: red;">+</span>'
|
68 |
+
})
|
69 |
+
}).addTo(map);
|
70 |
+
}
|
71 |
+
});
|
dashboard/templates/dashboard/aiAgent.html
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>Title</title>
|
6 |
+
</head>
|
7 |
+
<body>
|
8 |
+
|
9 |
+
</body>
|
10 |
+
</html>
|
dashboard/templates/dashboard/company_detail.html
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
{% load static %}
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
<link rel="stylesheet" href="{% static 'dashboard/style.css' %}">
|
8 |
+
<title>{{ company.name }} - Details</title>
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<div class="hero">
|
12 |
+
<h1>{{ company.name }}</h1>
|
13 |
+
<p>Details for {{ company.name }} in {{ company.country.name }}</p>
|
14 |
+
</div>
|
15 |
+
<div class="features">
|
16 |
+
<h2>Financial Data</h2>
|
17 |
+
<div class="container">
|
18 |
+
<h3>Aktiva</h3>
|
19 |
+
<ul>
|
20 |
+
<li>Anlagevermögen: {{ company.balance_sheet.Aktiva.Anlagevermögen }}</li>
|
21 |
+
<li>Umlaufvermögen: {{ company.balance_sheet.Aktiva.Umlaufvermögen }}</li>
|
22 |
+
</ul>
|
23 |
+
<h3>Passiva</h3>
|
24 |
+
<ul>
|
25 |
+
<li>Eigenkapital: {{ company.balance_sheet.Passiva.Eigenkapital }}</li>
|
26 |
+
<li>Fremdkapital: {{ company.balance_sheet.Passiva.Fremdkapital }}</li>
|
27 |
+
</ul>
|
28 |
+
</div>
|
29 |
+
</div>
|
30 |
+
<footer>
|
31 |
+
<p>© 2024 Pillar 2 Dashboard</p>
|
32 |
+
</footer>
|
33 |
+
</body>
|
34 |
+
</html>
|
dashboard/templates/dashboard/connectors.html
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>Title</title>
|
6 |
+
</head>
|
7 |
+
<body>
|
8 |
+
|
9 |
+
</body>
|
10 |
+
</html>
|
dashboard/templates/dashboard/country_detail.html
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
{% load static %}
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
<link rel="stylesheet" href="{% static 'dashboard/style.css' %}">
|
8 |
+
<title>{{ country.name }} - {{ data.year }}</title>
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<div class="hero">
|
12 |
+
<h1>{{ country.name }} - {{ data.year }}</h1>
|
13 |
+
<p>Details for {{ data.company_name }}</p>
|
14 |
+
</div>
|
15 |
+
<div class="features">
|
16 |
+
<h2>Financial Data</h2>
|
17 |
+
<div class="feature">
|
18 |
+
<p><strong>Balance Sheet:</strong> {{ data.balance_sheet }}</p>
|
19 |
+
<p><strong>Plausibility:</strong> {% if data.is_plausible %}✔️ Plausible{% else %}❌ Implausible{% endif %}</p>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<h3>Actions</h3>
|
23 |
+
<button class="cta-button" onclick="markImplausible()">Mark as Implausible</button>
|
24 |
+
<h3>Send Questionnaire</h3>
|
25 |
+
<form id="questionnaire-form">
|
26 |
+
<textarea name="question" placeholder="Enter your question"></textarea>
|
27 |
+
<button type="button" class="cta-button" onclick="sendQuestionnaire()">Send</button>
|
28 |
+
</form>
|
29 |
+
</div>
|
30 |
+
<h2>Balance Sheet</h2>
|
31 |
+
<div class="feature">
|
32 |
+
<h3>Aktiva</h3>
|
33 |
+
<ul>
|
34 |
+
<li>Anlagevermögen:
|
35 |
+
<ul>
|
36 |
+
<li>Sachanlagen: {{ data.balance_sheet.Aktiva.Anlagevermögen.Sachanlagen }}</li>
|
37 |
+
<li>immaterielle Vermögensgegenstände: {{ data.balance_sheet.Aktiva.Anlagevermögen.immaterielle_Vermögensgegenstände }}</li>
|
38 |
+
<li>Finanzanlagen: {{ data.balance_sheet.Aktiva.Anlagevermögen.Finanzanlagen }}</li>
|
39 |
+
</ul>
|
40 |
+
</li>
|
41 |
+
<li>Umlaufvermögen:
|
42 |
+
<ul>
|
43 |
+
<li>Vorräte: {{ data.balance_sheet.Aktiva.Umlaufvermögen.Vorräte }}</li>
|
44 |
+
<li>Forderungen: {{ data.balance_sheet.Aktiva.Umlaufvermögen.Forderungen }}</li>
|
45 |
+
<li>Kassenbestand: {{ data.balance_sheet.Aktiva.Umlaufvermögen.Kassenbestand }}</li>
|
46 |
+
<li>Wertpapiere: {{ data.balance_sheet.Aktiva.Umlaufvermögen.Wertpapiere }}</li>
|
47 |
+
</ul>
|
48 |
+
</li>
|
49 |
+
</ul>
|
50 |
+
<h3>Passiva</h3>
|
51 |
+
<ul>
|
52 |
+
<li>Eigenkapital:
|
53 |
+
<ul>
|
54 |
+
<li>Gezeichnetes Kapital: {{ data.balance_sheet.Passiva.Eigenkapital.Gezeichnetes_Kapital }}</li>
|
55 |
+
<li>Kapitalrücklagen: {{ data.balance_sheet.Passiva.Eigenkapital.Kapitalrücklagen }}</li>
|
56 |
+
<li>Gewinnrücklagen: {{ data.balance_sheet.Passiva.Eigenkapital.Gewinnrücklagen }}</li>
|
57 |
+
</ul>
|
58 |
+
</li>
|
59 |
+
<li>Fremdkapital:
|
60 |
+
<ul>
|
61 |
+
<li>Kurzfristige Verbindlichkeiten: {{ data.balance_sheet.Passiva.Fremdkapital.Kurzfristige_Verbindlichkeiten }}</li>
|
62 |
+
<li>langfristige Verbindlichkeiten: {{ data.balance_sheet.Passiva.Fremdkapital.langfristige_Verbindlichkeiten }}</li>
|
63 |
+
</ul>
|
64 |
+
</li>
|
65 |
+
</ul>
|
66 |
+
</div>
|
67 |
+
<footer>
|
68 |
+
<p>© 2024 Pillar 2 Dashboard</p>
|
69 |
+
</footer>
|
70 |
+
<script>
|
71 |
+
function markImplausible() {
|
72 |
+
fetch("{% url 'mark_implausible' data.id %}", {
|
73 |
+
method: "POST",
|
74 |
+
headers: {
|
75 |
+
"X-CSRFToken": "{{ csrf_token }}"
|
76 |
+
}
|
77 |
+
}).then(response => response.json())
|
78 |
+
.then(data => {
|
79 |
+
if (data.status === "success") {
|
80 |
+
alert("Marked as implausible!");
|
81 |
+
location.reload();
|
82 |
+
}
|
83 |
+
});
|
84 |
+
}
|
85 |
+
|
86 |
+
function sendQuestionnaire() {
|
87 |
+
const question = document.querySelector('textarea[name="question"]').value;
|
88 |
+
fetch("{% url 'send_questionnaire' data.id %}", {
|
89 |
+
method: "POST",
|
90 |
+
headers: {
|
91 |
+
"X-CSRFToken": "{{ csrf_token }}",
|
92 |
+
"Content-Type": "application/json"
|
93 |
+
},
|
94 |
+
body: JSON.stringify({ question: question })
|
95 |
+
}).then(response => response.json())
|
96 |
+
.then(data => {
|
97 |
+
if (data.status === "questionnaire_created") {
|
98 |
+
alert("Questionnaire sent!");
|
99 |
+
location.reload();
|
100 |
+
}
|
101 |
+
});
|
102 |
+
}
|
103 |
+
</script>
|
104 |
+
</body>
|
105 |
+
</html>
|
dashboard/templates/dashboard/country_list.html
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
{% load static %}
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
<link rel="stylesheet" href="{% static 'dashboard/style.css' %}">
|
8 |
+
<title>Country Overview</title>
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<div class="hero">
|
12 |
+
<h1>Country Overview</h1>
|
13 |
+
<p>Explore financial data for each company by country</p>
|
14 |
+
</div>
|
15 |
+
<div class="features">
|
16 |
+
<h2>Available Countries and Companies</h2>
|
17 |
+
<div class="container">
|
18 |
+
<ul>
|
19 |
+
{% for country in countries %}
|
20 |
+
<li style="list-style: none;">
|
21 |
+
<div class="country-card" style="background-color: #e1efff; padding: 20px; margin-bottom: 20px; border-radius: 8px;">
|
22 |
+
<h3 style="color: #007bb5;">{{ country.name }}</h3>
|
23 |
+
<h4 style="margin-top: 10px;">Companies:</h4>
|
24 |
+
<ul>
|
25 |
+
{% for company in country.companies.all %} <!-- Correct company loop -->
|
26 |
+
<li style="margin: 5px 0;">
|
27 |
+
<a href="{% url 'company_detail' company.id %}" class="company-link" style="color: #007bb5;">{{ company.name }}</a>
|
28 |
+
</li>
|
29 |
+
{% endfor %}
|
30 |
+
</ul>
|
31 |
+
</div>
|
32 |
+
</li>
|
33 |
+
{% endfor %} <!-- Ensure only one loop ends here -->
|
34 |
+
|
35 |
+
</ul>
|
36 |
+
|
37 |
+
<footer>
|
38 |
+
<p>© 2024 Pillar 2 Dashboard</p>
|
39 |
+
</footer>
|
40 |
+
</body>
|
41 |
+
</html>
|
dashboard/templates/dashboard/dashboard.html
ADDED
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Pillar 2 Dashboard</title>
|
7 |
+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
|
8 |
+
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<h1>Pillar 2 Dashboard</h1>
|
12 |
+
<div id="map" style="height: 500px;"></div>
|
13 |
+
<script>
|
14 |
+
const countries = [
|
15 |
+
|
16 |
+
{
|
17 |
+
name: "Australia",
|
18 |
+
iso_code: "AU",
|
19 |
+
latitude: -35.2809, // Hauptstadt: Canberra
|
20 |
+
longitude: 149.1300,
|
21 |
+
pillar2_implemented: true,
|
22 |
+
local_top_up_tax: true
|
23 |
+
},
|
24 |
+
{
|
25 |
+
name: "Brazil",
|
26 |
+
iso_code: "BR",
|
27 |
+
latitude: -15.7801, // Hauptstadt: Brasília
|
28 |
+
longitude: -47.9292,
|
29 |
+
pillar2_implemented: true,
|
30 |
+
local_top_up_tax: true
|
31 |
+
},
|
32 |
+
{
|
33 |
+
name: "Canada",
|
34 |
+
iso_code: "CA",
|
35 |
+
latitude: 45.4215, // Hauptstadt: Ottawa
|
36 |
+
longitude: -75.6972,
|
37 |
+
pillar2_implemented: true,
|
38 |
+
local_top_up_tax: true
|
39 |
+
},
|
40 |
+
{
|
41 |
+
name: "Germany",
|
42 |
+
iso_code: "DE",
|
43 |
+
latitude: 52.5200, // Hauptstadt: Berlin
|
44 |
+
longitude: 13.4050,
|
45 |
+
pillar2_implemented: true,
|
46 |
+
local_top_up_tax: true
|
47 |
+
},
|
48 |
+
{
|
49 |
+
name: "France",
|
50 |
+
iso_code: "FR",
|
51 |
+
latitude: 48.8566, // Hauptstadt: Paris
|
52 |
+
longitude: 2.3522,
|
53 |
+
pillar2_implemented: true,
|
54 |
+
local_top_up_tax: true
|
55 |
+
},
|
56 |
+
{
|
57 |
+
name: "United Kingdom",
|
58 |
+
iso_code: "GB",
|
59 |
+
latitude: 51.5074, // Hauptstadt: London
|
60 |
+
longitude: -0.1278,
|
61 |
+
pillar2_implemented: true,
|
62 |
+
local_top_up_tax: true
|
63 |
+
},
|
64 |
+
{
|
65 |
+
name: "Italy",
|
66 |
+
iso_code: "IT",
|
67 |
+
latitude: 41.9028, // Hauptstadt: Rom
|
68 |
+
longitude: 12.4964,
|
69 |
+
pillar2_implemented: true,
|
70 |
+
local_top_up_tax: true
|
71 |
+
},
|
72 |
+
{
|
73 |
+
name: "Spain",
|
74 |
+
iso_code: "ES",
|
75 |
+
latitude: 40.4168, // Hauptstadt: Madrid
|
76 |
+
longitude: -3.7038,
|
77 |
+
pillar2_implemented: true,
|
78 |
+
local_top_up_tax: true
|
79 |
+
},
|
80 |
+
{
|
81 |
+
name: "Japan",
|
82 |
+
iso_code: "JP",
|
83 |
+
latitude: 35.6762, // Hauptstadt: Tokio
|
84 |
+
longitude: 139.6503,
|
85 |
+
pillar2_implemented: true,
|
86 |
+
local_top_up_tax: true
|
87 |
+
},
|
88 |
+
{
|
89 |
+
name: "South Korea",
|
90 |
+
iso_code: "KR",
|
91 |
+
latitude: 37.5665, // Hauptstadt: Seoul
|
92 |
+
longitude: 126.9780,
|
93 |
+
pillar2_implemented: true,
|
94 |
+
local_top_up_tax: false
|
95 |
+
},
|
96 |
+
{
|
97 |
+
name: "Netherlands",
|
98 |
+
iso_code: "NL",
|
99 |
+
latitude: 52.3676, // Hauptstadt: Amsterdam
|
100 |
+
longitude: 4.9041,
|
101 |
+
pillar2_implemented: true,
|
102 |
+
local_top_up_tax: true
|
103 |
+
},
|
104 |
+
{
|
105 |
+
name: "Sweden",
|
106 |
+
iso_code: "SE",
|
107 |
+
latitude: 59.3293, // Hauptstadt: Stockholm
|
108 |
+
longitude: 18.0686,
|
109 |
+
pillar2_implemented: true,
|
110 |
+
local_top_up_tax: true
|
111 |
+
},
|
112 |
+
{
|
113 |
+
name: "Poland",
|
114 |
+
iso_code: "PL",
|
115 |
+
latitude: 52.2298, // Hauptstadt: Warschau
|
116 |
+
longitude: 21.0118,
|
117 |
+
pillar2_implemented: true,
|
118 |
+
local_top_up_tax: true
|
119 |
+
},
|
120 |
+
{
|
121 |
+
name: "India",
|
122 |
+
iso_code: "IN",
|
123 |
+
latitude: 28.6139, // Hauptstadt: New Delhi
|
124 |
+
longitude: 77.2090,
|
125 |
+
pillar2_implemented: false,
|
126 |
+
local_top_up_tax: false
|
127 |
+
},
|
128 |
+
{
|
129 |
+
name: "United States",
|
130 |
+
iso_code: "US",
|
131 |
+
latitude: 38.8954, // Hauptstadt: Washington, D.C.
|
132 |
+
longitude: -77.0365,
|
133 |
+
pillar2_implemented: false,
|
134 |
+
local_top_up_tax: false
|
135 |
+
},
|
136 |
+
{
|
137 |
+
name: "Mexico",
|
138 |
+
iso_code: "MX",
|
139 |
+
latitude: 19.4326, // Hauptstadt: Mexiko-Stadt
|
140 |
+
longitude: -99.1332,
|
141 |
+
pillar2_implemented: false,
|
142 |
+
local_top_up_tax: false
|
143 |
+
},
|
144 |
+
{
|
145 |
+
name: "China",
|
146 |
+
iso_code: "CN",
|
147 |
+
latitude: 39.9042, // Hauptstadt: Peking
|
148 |
+
longitude: 116.4074,
|
149 |
+
pillar2_implemented: false,
|
150 |
+
local_top_up_tax: false
|
151 |
+
},
|
152 |
+
{
|
153 |
+
name: "Norway",
|
154 |
+
iso_code: "NO",
|
155 |
+
latitude: 59.9139, // Hauptstadt: Oslo
|
156 |
+
longitude: 10.7522,
|
157 |
+
pillar2_implemented: true,
|
158 |
+
local_top_up_tax: true
|
159 |
+
},
|
160 |
+
{
|
161 |
+
name: "Finland",
|
162 |
+
iso_code: "FI",
|
163 |
+
latitude: 60.1695, // Hauptstadt: Helsinki
|
164 |
+
longitude: 24.9354,
|
165 |
+
pillar2_implemented: true,
|
166 |
+
local_top_up_tax: true
|
167 |
+
},
|
168 |
+
{
|
169 |
+
name: "Switzerland",
|
170 |
+
iso_code: "CH",
|
171 |
+
latitude: 46.9481, // Hauptstadt: Bern
|
172 |
+
longitude: 7.4474,
|
173 |
+
pillar2_implemented: true,
|
174 |
+
local_top_up_tax: true
|
175 |
+
},
|
176 |
+
{
|
177 |
+
name: "Austria",
|
178 |
+
iso_code: "AT",
|
179 |
+
latitude: 48.2082, // Hauptstadt: Wien
|
180 |
+
longitude: 16.3738,
|
181 |
+
pillar2_implemented: true,
|
182 |
+
local_top_up_tax: true
|
183 |
+
},
|
184 |
+
{
|
185 |
+
name: "Ireland",
|
186 |
+
iso_code: "IE",
|
187 |
+
latitude: 53.3498, // Hauptstadt: Dublin
|
188 |
+
longitude: -6.2603,
|
189 |
+
pillar2_implemented: true,
|
190 |
+
local_top_up_tax: true
|
191 |
+
},
|
192 |
+
{
|
193 |
+
name: "Luxembourg",
|
194 |
+
iso_code: "LU",
|
195 |
+
latitude: 49.6117, // Hauptstadt: Luxemburg
|
196 |
+
longitude: 6.13,
|
197 |
+
pillar2_implemented: true,
|
198 |
+
local_top_up_tax: true
|
199 |
+
},
|
200 |
+
{
|
201 |
+
name: "Belgium",
|
202 |
+
iso_code: "BE",
|
203 |
+
latitude: 50.8503, // Hauptstadt: Brüssel
|
204 |
+
longitude: 4.3517,
|
205 |
+
pillar2_implemented: true,
|
206 |
+
local_top_up_tax: true
|
207 |
+
},
|
208 |
+
{
|
209 |
+
name: "Denmark",
|
210 |
+
iso_code: "DK",
|
211 |
+
latitude: 55.6761, // Hauptstadt: Kopenhagen
|
212 |
+
longitude: 12.5683,
|
213 |
+
pillar2_implemented: true,
|
214 |
+
local_top_up_tax: true
|
215 |
+
},
|
216 |
+
{
|
217 |
+
name: "Portugal",
|
218 |
+
iso_code: "PT",
|
219 |
+
latitude: 38.7169, // Hauptstadt: Lissabon
|
220 |
+
longitude: -9.1395,
|
221 |
+
pillar2_implemented: true,
|
222 |
+
local_top_up_tax: true
|
223 |
+
}
|
224 |
+
|
225 |
+
];
|
226 |
+
|
227 |
+
// Initialize map
|
228 |
+
const map = L.map('map').setView([20, 0], 2);
|
229 |
+
|
230 |
+
// Add OpenStreetMap tiles
|
231 |
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
232 |
+
maxZoom: 19
|
233 |
+
}).addTo(map);
|
234 |
+
|
235 |
+
// Define a custom icon for the red arrow
|
236 |
+
const redArrowIcon = L.divIcon({
|
237 |
+
className: 'custom-icon', // Define CSS class
|
238 |
+
html: `<div style="width: 0; height: 0;
|
239 |
+
border-left: 3px solid transparent;
|
240 |
+
border-right: 3px solid transparent;
|
241 |
+
border-bottom: 6px solid red;
|
242 |
+
transform: rotate(0deg);">
|
243 |
+
</div>`,
|
244 |
+
iconSize: [20, 20],
|
245 |
+
iconAnchor: [10, 10] // Adjust so the arrow points at the correct position
|
246 |
+
});
|
247 |
+
|
248 |
+
// Add countries to map
|
249 |
+
countries.forEach(country => {
|
250 |
+
const color = country.pillar2_implemented ? 'green' : 'gray';
|
251 |
+
|
252 |
+
// Add circle marker for each country
|
253 |
+
L.circleMarker([country.latitude, country.longitude], {
|
254 |
+
color: color,
|
255 |
+
radius: 10
|
256 |
+
}).addTo(map).bindPopup(`${country.name}`);
|
257 |
+
|
258 |
+
// Add red arrow marker for Local Top-Up Tax
|
259 |
+
if (country.local_top_up_tax) {
|
260 |
+
L.marker([country.latitude, country.longitude], {
|
261 |
+
icon: redArrowIcon // Use the custom red arrow icon
|
262 |
+
}).addTo(map);
|
263 |
+
}
|
264 |
+
});
|
265 |
+
</script>
|
266 |
+
</body>
|
267 |
+
</html>
|
dashboard/templates/dashboard/masterData.html
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>Title</title>
|
6 |
+
</head>
|
7 |
+
<body>
|
8 |
+
|
9 |
+
</body>
|
10 |
+
</html>
|
dashboard/templates/dashboard/start_page.html
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
{% load static %}
|
3 |
+
<html lang="en">
|
4 |
+
<head>
|
5 |
+
<meta charset="UTF-8">
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7 |
+
<title>Your Tax-Cockpit</title>
|
8 |
+
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap">
|
9 |
+
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
10 |
+
</head>
|
11 |
+
<body>
|
12 |
+
<section class="hero">
|
13 |
+
<div class="container">
|
14 |
+
<h1>Your Tax-Cockpit</h1>
|
15 |
+
<p>Get an overview about our functions</p>
|
16 |
+
<a href="{% url 'dashboard' %}" class="cta-button">Show a Pillar 2 overview Map</a>
|
17 |
+
</div>
|
18 |
+
<div class="container">
|
19 |
+
<a href="{% url 'country_list' %}" class="cta-button">Show me our country data</a>
|
20 |
+
</div>
|
21 |
+
</section>
|
22 |
+
|
23 |
+
<section class="configuration">
|
24 |
+
<div class="container">
|
25 |
+
<h1>Configuration</h1>
|
26 |
+
<a href="{% url 'masterData' %}" class="cta-button">Add your Master-Data</a>
|
27 |
+
|
28 |
+
</div>
|
29 |
+
<div class="container">
|
30 |
+
<a href="{% url 'connectors' %}" class="cta-button">Set up your connections</a>
|
31 |
+
</div>
|
32 |
+
|
33 |
+
<div class="container">
|
34 |
+
<a href="{% url 'userManagement' %}" class="cta-button">User-Management</a>
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<div class="container">
|
38 |
+
<a href="{% url 'aiAgent' %}" class="cta-button">Ask our AI-Agent</a>
|
39 |
+
</div>
|
40 |
+
|
41 |
+
</section>
|
42 |
+
|
43 |
+
<section id="learn-more" class="features">
|
44 |
+
<div class="container">
|
45 |
+
<h2>What We Offer</h2>
|
46 |
+
<div class="feature">
|
47 |
+
<h3>Connect your Systems</h3>
|
48 |
+
<h3>Keep your Data in one place</h3>
|
49 |
+
<h3>Modular dashboard, different use-cases can be added </h3>
|
50 |
+
</div>
|
51 |
+
|
52 |
+
</div>
|
53 |
+
</section>
|
54 |
+
|
55 |
+
<footer>
|
56 |
+
<div class="container">
|
57 |
+
<p>© 2024 My Django Site. All Rights Reserved.</p>
|
58 |
+
</div>
|
59 |
+
</footer>
|
60 |
+
</body>
|
61 |
+
</html>
|
dashboard/templates/dashboard/userManagement.html
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<title>Title</title>
|
6 |
+
</head>
|
7 |
+
<body>
|
8 |
+
|
9 |
+
</body>
|
10 |
+
</html>
|
dashboard/tests.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from django.test import TestCase
|
2 |
+
|
3 |
+
# Create your tests here.
|
dashboard/urls.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.urls import path
|
2 |
+
from . import views
|
3 |
+
from .views import (
|
4 |
+
StartPageView,
|
5 |
+
masterData,
|
6 |
+
connectors,
|
7 |
+
userManagement,
|
8 |
+
aiAgent,)
|
9 |
+
|
10 |
+
|
11 |
+
urlpatterns = [
|
12 |
+
path('', StartPageView.as_view(), name='start_page'), # Startseite
|
13 |
+
path('overview', views.dashboard, name='dashboard'), # Dashboard
|
14 |
+
path('masterData', masterData, name='masterData'), # Master Data
|
15 |
+
path('connectors', connectors, name='connectors'), # Connectors
|
16 |
+
path('userManagement', userManagement, name='userManagement'), # User Management
|
17 |
+
path('aiAgent', aiAgent, name='aiAgent'), # AI Agent
|
18 |
+
path('countries/', views.country_list, name='country_list'),
|
19 |
+
path('countries/<int:country_id>/<int:year>/', views.country_detail, name='country_detail'),
|
20 |
+
path('mark_implausible/<int:country_data_id>/', views.mark_implausible, name='mark_implausible'),
|
21 |
+
path('send_questionnaire/<int:country_data_id>/', views.send_questionnaire, name='send_questionnaire'),
|
22 |
+
path('companies/<int:company_id>/', views.company_detail, name='company_detail'),
|
23 |
+
|
24 |
+
]
|
dashboard/views.py
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.http import JsonResponse
|
2 |
+
from django.shortcuts import render, get_object_or_404
|
3 |
+
from django.views.decorators.csrf import csrf_exempt
|
4 |
+
from django.shortcuts import render, get_object_or_404, redirect
|
5 |
+
from .models import Country, CountryData, Questionnaire
|
6 |
+
from django.http import JsonResponse
|
7 |
+
from django.views.decorators.csrf import csrf_exempt
|
8 |
+
from .models import Country
|
9 |
+
from django.views.generic import ListView, DetailView, CreateView, UpdateView, TemplateView
|
10 |
+
|
11 |
+
class StartPageView(TemplateView):
|
12 |
+
template_name = "dashboard/start_page.html"
|
13 |
+
|
14 |
+
def dashboard(request):
|
15 |
+
countries = Country.objects.all()
|
16 |
+
country_data = [
|
17 |
+
{
|
18 |
+
"name": country.name,
|
19 |
+
"iso_code": country.iso_code,
|
20 |
+
"latitude": country.latitude,
|
21 |
+
"longitude": country.longitude,
|
22 |
+
"pillar2_implemented": country.pillar2_implemented,
|
23 |
+
"local_top_up_tax": country.local_top_up_tax,
|
24 |
+
}
|
25 |
+
for country in countries
|
26 |
+
]
|
27 |
+
return render(request, 'dashboard/dashboard.html', {"countries": country_data})
|
28 |
+
|
29 |
+
|
30 |
+
def country_list(request):
|
31 |
+
countries = Country.objects.all()
|
32 |
+
return render(request, 'dashboard/country_list.html', {'countries': countries})
|
33 |
+
|
34 |
+
def country_detail(request, country_id, year):
|
35 |
+
country = get_object_or_404(Country, id=country_id)
|
36 |
+
data = get_object_or_404(CountryData, country=country, year=year)
|
37 |
+
questionnaires = data.questionnaires.all()
|
38 |
+
return render(request, 'dashboard/country_detail.html', {
|
39 |
+
'country': country,
|
40 |
+
'data': data,
|
41 |
+
'questionnaires': questionnaires,
|
42 |
+
})
|
43 |
+
|
44 |
+
@csrf_exempt
|
45 |
+
def mark_implausible(request, country_data_id):
|
46 |
+
if request.method == 'POST':
|
47 |
+
data = get_object_or_404(CountryData, id=country_data_id)
|
48 |
+
data.is_plausible = False
|
49 |
+
data.save()
|
50 |
+
return JsonResponse({'status': 'success'})
|
51 |
+
|
52 |
+
@csrf_exempt
|
53 |
+
def send_questionnaire(request, country_data_id):
|
54 |
+
if request.method == 'POST':
|
55 |
+
question = request.POST.get('question')
|
56 |
+
country_data = get_object_or_404(CountryData, id=country_data_id)
|
57 |
+
Questionnaire.objects.create(
|
58 |
+
country_data=country_data,
|
59 |
+
question=question,
|
60 |
+
created_by=request.user
|
61 |
+
)
|
62 |
+
return JsonResponse({'status': 'questionnaire_created'})
|
63 |
+
|
64 |
+
|
65 |
+
from django.shortcuts import render, get_object_or_404
|
66 |
+
from .models import Company
|
67 |
+
|
68 |
+
def company_detail(request, company_id):
|
69 |
+
company = get_object_or_404(Company, id=company_id)
|
70 |
+
return render(request, 'dashboard/company_detail.html', {"company": company})
|
71 |
+
|
72 |
+
def masterData(request):
|
73 |
+
return render(request, 'dashboard/masterData.html')
|
74 |
+
|
75 |
+
def connectors(request):
|
76 |
+
return render(request, 'dashboard/connectors.html')
|
77 |
+
|
78 |
+
def userManagement(request):
|
79 |
+
return render(request, 'dashboard/userManagement.html')
|
80 |
+
|
81 |
+
def aiAgent(request):
|
82 |
+
return render(request, 'dashboard/aiAgent.html')
|
docs/setup.md
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
Backend
|
2 |
-
|
3 |
-
Setup
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
git clone https://huggingface.co/spaces/gaganyatri/django_spaces
|
8 |
-
|
9 |
-
cd django_spaces
|
10 |
-
|
11 |
-
docker build -t slabstech/gaganyatri -f Dockerfile .
|
12 |
-
|
13 |
-
docker run slabstech/gaganyatri
|
14 |
-
|
15 |
-
|
16 |
-
- Steps to build this project
|
17 |
-
- python3.10 -m venv venv
|
18 |
-
- source venv/bin/activate
|
19 |
-
- pip install Django==5.1.1
|
20 |
-
- django-admin startproject spaces .
|
21 |
-
- python manage.py migrate
|
22 |
-
- python manage.py runserver
|
23 |
-
|
24 |
-
- python manage.py startapp space_walks
|
25 |
-
- python manage.py makemigrations
|
26 |
-
- python manage.py migrate
|
27 |
-
|
28 |
-
|
29 |
-
- pip install uvicorn
|
30 |
-
- python -m uvicorn spaces.asgi:application
|
31 |
-
|
32 |
-
|
33 |
-
- Merge for Huggingface
|
34 |
-
- git fetch --all
|
35 |
-
- git checkout main
|
36 |
-
- git merge --squash django-setup
|
37 |
-
- git commit -m "merge"
|
38 |
-
- git push origin main
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
- Referenc
|
43 |
-
- https://www.djangoproject.com/download/
|
44 |
-
- https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/
|
45 |
-
- https://github.com/testdrivenio/django-on-docker
|
46 |
-
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
games/__init__.py
ADDED
File without changes
|
games/admin.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.contrib import admin
|
2 |
+
from .models import Game
|
3 |
+
|
4 |
+
admin.site.register(Game)
|
games/apps.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.apps import AppConfig
|
2 |
+
|
3 |
+
|
4 |
+
class GamesConfig(AppConfig):
|
5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
6 |
+
name = 'games'
|
games/migrations/0001_initial.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Generated by Django 5.1.1 on 2024-10-31 09:32
|
2 |
+
|
3 |
+
from django.db import migrations, models
|
4 |
+
|
5 |
+
|
6 |
+
class Migration(migrations.Migration):
|
7 |
+
|
8 |
+
initial = True
|
9 |
+
|
10 |
+
dependencies = [
|
11 |
+
]
|
12 |
+
|
13 |
+
operations = [
|
14 |
+
migrations.CreateModel(
|
15 |
+
name='Game',
|
16 |
+
fields=[
|
17 |
+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
18 |
+
('name', models.CharField(max_length=200)),
|
19 |
+
('description', models.TextField()),
|
20 |
+
('release_date', models.DateField()),
|
21 |
+
],
|
22 |
+
),
|
23 |
+
]
|
games/migrations/__init__.py
ADDED
File without changes
|
games/models.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.db import models
|
2 |
+
|
3 |
+
class Game(models.Model):
|
4 |
+
name = models.CharField(max_length=200)
|
5 |
+
description = models.TextField()
|
6 |
+
release_date = models.DateField()
|
games/templates/game_list.html
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html>
|
3 |
+
<head>
|
4 |
+
<title>Game List</title>
|
5 |
+
</head>
|
6 |
+
<body>
|
7 |
+
<h1>Games</h1>
|
8 |
+
{% for game in games %}
|
9 |
+
<li>
|
10 |
+
<h2>{{ game.name }}</h2>
|
11 |
+
<p>{{ game.description }}</p>
|
12 |
+
<p>Released on: {{ game.release_date }}</p>
|
13 |
+
</li>
|
14 |
+
{% endfor %}
|
15 |
+
</body>
|
16 |
+
</html>
|
games/tests.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from django.test import TestCase
|
2 |
+
|
3 |
+
# Create your tests here.
|
games/urls.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.urls import path
|
2 |
+
from . import views
|
3 |
+
|
4 |
+
urlpatterns = [
|
5 |
+
path('', views.game_list, name='game_list'),
|
6 |
+
]
|
games/views.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.shortcuts import render
|
2 |
+
from .models import Game
|
3 |
+
|
4 |
+
def game_list(request):
|
5 |
+
games = Game.objects.all()
|
6 |
+
return render(request, 'games/game_list.html', {'games': games})
|
inference/__init__.py
ADDED
File without changes
|
inference/admin.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from django.contrib import admin
|
2 |
+
|
3 |
+
# Register your models here.
|
inference/apps.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.apps import AppConfig
|
2 |
+
|
3 |
+
|
4 |
+
class InferenceConfig(AppConfig):
|
5 |
+
default_auto_field = 'django.db.models.BigAutoField'
|
6 |
+
name = 'inference'
|
inference/migrations/__init__.py
ADDED
File without changes
|
inference/models.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from django.db import models
|
2 |
+
|
3 |
+
# Create your models here.
|
inference/tests.py
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
from django.test import TestCase
|
2 |
+
|
3 |
+
# Create your tests here.
|
inference/urls.py
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.urls import path
|
2 |
+
from .views import VisionLLMView, NIMVisionLLMView, TextLLMView, TranslateLLMView, SpeechLLMView, LlamaVisionView, IndicLLMView, TTSView, SpeechASRView, SpeechToSpeechView
|
3 |
+
|
4 |
+
urlpatterns = [
|
5 |
+
path('vision_llm_url/', VisionLLMView.as_view()),
|
6 |
+
path('nim_vision_llm_url/', NIMVisionLLMView.as_view()),
|
7 |
+
path('text_llm_url/', TextLLMView.as_view()),
|
8 |
+
path('translate_llm_url/', TranslateLLMView.as_view()),
|
9 |
+
path('speech_llm_url/', SpeechLLMView.as_view()),
|
10 |
+
path('speech_asr_url/', SpeechASRView.as_view()),
|
11 |
+
path('llama_vision_url/', LlamaVisionView.as_view()),
|
12 |
+
path('indic_llm_url/', IndicLLMView.as_view()),
|
13 |
+
path('tts_url/', TTSView.as_view()),
|
14 |
+
path('speech_to_speech_url/', SpeechToSpeechView.as_view()),
|
15 |
+
]
|
inference/views.py
ADDED
@@ -0,0 +1,430 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from django.http import JsonResponse
|
2 |
+
from rest_framework.response import Response
|
3 |
+
from rest_framework.views import APIView
|
4 |
+
from mistralai import Mistral
|
5 |
+
import os
|
6 |
+
import requests
|
7 |
+
from openai import OpenAI
|
8 |
+
from ollama import Client
|
9 |
+
from django.http import FileResponse
|
10 |
+
import io
|
11 |
+
|
12 |
+
class TTSView(APIView):
|
13 |
+
def post(self, request, format=None):
|
14 |
+
# Define the API endpoint
|
15 |
+
# Define the URL for the TTS API
|
16 |
+
url = 'http://localhost:5002/api/tts'
|
17 |
+
|
18 |
+
# Define the multiline text
|
19 |
+
text = "This is the first line"
|
20 |
+
|
21 |
+
# Prepare the parameters for the GET request
|
22 |
+
params = {
|
23 |
+
'text': text
|
24 |
+
}
|
25 |
+
|
26 |
+
# Make the GET request
|
27 |
+
response = requests.get(url, params=params)
|
28 |
+
|
29 |
+
# Check if the request was successful
|
30 |
+
if response.status_code == 200:
|
31 |
+
# Save the audio response as a WAV file
|
32 |
+
# Create a file-like object with the audio data
|
33 |
+
audio_data = io.BytesIO(response.content)
|
34 |
+
|
35 |
+
# Return the audio file as a response
|
36 |
+
return FileResponse(audio_data, as_attachment=True, filename='audio_output.wav')
|
37 |
+
else:
|
38 |
+
return Response({"error": "Failed to synthesize speech"}, status=response.status_code)
|
39 |
+
|
40 |
+
class SpeechASRView(APIView):
|
41 |
+
def post(self, request, format=None):
|
42 |
+
try:
|
43 |
+
data = request.data
|
44 |
+
##prompt = data['prompt']
|
45 |
+
audio = data['audio']
|
46 |
+
print('hre1')
|
47 |
+
client = OpenAI(api_key="cant-be-empty", base_url="http://0.0.0.0:11800/v1/")
|
48 |
+
print('her2')
|
49 |
+
#filename= '/home/gaganyatri/Music/test1.flac'
|
50 |
+
audio_bytes = audio.read()
|
51 |
+
|
52 |
+
#audio_file = open(filename, "rb")
|
53 |
+
|
54 |
+
transcript = client.audio.transcriptions.create(
|
55 |
+
model="Systran/faster-distil-whisper-small.en", file=audio_bytes
|
56 |
+
)
|
57 |
+
|
58 |
+
#print(transcript.text)
|
59 |
+
voice_content = transcript.text
|
60 |
+
return Response({"response": voice_content})
|
61 |
+
except Exception as e:
|
62 |
+
print(f"An error occurred: {e}")
|
63 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
64 |
+
|
65 |
+
|
66 |
+
class SpeechToSpeechView(APIView):
|
67 |
+
def post(self, request, format=None):
|
68 |
+
try:
|
69 |
+
data = request.data
|
70 |
+
##prompt = data['prompt']
|
71 |
+
audio = data['audio']
|
72 |
+
|
73 |
+
client = OpenAI(api_key="cant-be-empty", base_url="http://0.0.0.0:11800/v1/")
|
74 |
+
|
75 |
+
#filename= '/home/gaganyatri/Music/test1.flac'
|
76 |
+
audio_bytes = audio.read()
|
77 |
+
|
78 |
+
#audio_file = open(filename, "rb")
|
79 |
+
|
80 |
+
transcript = client.audio.transcriptions.create(
|
81 |
+
model="Systran/faster-distil-whisper-small.en", file=audio_bytes
|
82 |
+
)
|
83 |
+
|
84 |
+
#print(transcript.text)
|
85 |
+
voice_content = transcript.text
|
86 |
+
#content = 'audio recieved'
|
87 |
+
system_prompt = "Please summarize the following prompt into a concise and clear statement:"
|
88 |
+
|
89 |
+
|
90 |
+
model = "mistral-nemo:latest"
|
91 |
+
client = Client(host='http://localhost:11434')
|
92 |
+
response = client.chat(
|
93 |
+
model=model,
|
94 |
+
messages=[
|
95 |
+
{
|
96 |
+
"role": "system",
|
97 |
+
"content": system_prompt
|
98 |
+
},
|
99 |
+
{
|
100 |
+
"role": "user",
|
101 |
+
"content": voice_content,
|
102 |
+
}
|
103 |
+
],
|
104 |
+
)
|
105 |
+
|
106 |
+
# Extract the model's response about the image
|
107 |
+
response_text = response['message']['content'].strip()
|
108 |
+
|
109 |
+
url = 'http://localhost:5002/api/tts'
|
110 |
+
|
111 |
+
# Define the multiline text
|
112 |
+
#text = "This is the first line"
|
113 |
+
|
114 |
+
# Prepare the parameters for the GET request
|
115 |
+
params = {
|
116 |
+
'text': response_text
|
117 |
+
}
|
118 |
+
|
119 |
+
# Make the GET request
|
120 |
+
response = requests.get(url, params=params)
|
121 |
+
|
122 |
+
# Check if the request was successful
|
123 |
+
if response.status_code == 200:
|
124 |
+
# Save the audio response as a WAV file
|
125 |
+
# Create a file-like object with the audio data
|
126 |
+
audio_data = io.BytesIO(response.content)
|
127 |
+
|
128 |
+
# Return the audio file as a response
|
129 |
+
return FileResponse(audio_data, as_attachment=True, filename='audio_output.wav')
|
130 |
+
else:
|
131 |
+
return Response({"error": "Failed to synthesize speech"}, status=response.status_code)
|
132 |
+
|
133 |
+
except Exception as e:
|
134 |
+
print(f"An error occurred: {e}")
|
135 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
136 |
+
|
137 |
+
class SpeechLLMView(APIView):
|
138 |
+
def post(self, request, format=None):
|
139 |
+
try:
|
140 |
+
data = request.data
|
141 |
+
##prompt = data['prompt']
|
142 |
+
audio = data['audio']
|
143 |
+
|
144 |
+
client = OpenAI(api_key="cant-be-empty", base_url="http://localhost:11800/v1/")
|
145 |
+
|
146 |
+
#filename= '/home/gaganyatri/Music/test1.flac'
|
147 |
+
audio_bytes = audio.read()
|
148 |
+
|
149 |
+
#audio_file = open(filename, "rb")
|
150 |
+
|
151 |
+
transcript = client.audio.transcriptions.create(
|
152 |
+
model="Systran/faster-distil-whisper-small.en", file=audio_bytes
|
153 |
+
)
|
154 |
+
|
155 |
+
#print(transcript.text)
|
156 |
+
voice_content = transcript.text
|
157 |
+
#content = 'audio recieved'
|
158 |
+
|
159 |
+
model = "mistral-nemo:latest"
|
160 |
+
client = Client(host='http://localhost:11434')
|
161 |
+
response = client.chat(
|
162 |
+
model=model,
|
163 |
+
messages=[{
|
164 |
+
"role": "user",
|
165 |
+
"content": voice_content,
|
166 |
+
}],
|
167 |
+
)
|
168 |
+
|
169 |
+
# Extract the model's response about the image
|
170 |
+
response_text = response['message']['content'].strip()
|
171 |
+
|
172 |
+
return Response({"response": response_text})
|
173 |
+
except Exception as e:
|
174 |
+
print(f"An error occurred: {e}")
|
175 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
176 |
+
|
177 |
+
class TranslateLLMView(APIView):
|
178 |
+
def post(self, request, format=None):
|
179 |
+
try:
|
180 |
+
data = request.data
|
181 |
+
prompt = data['messages'][0]['prompt']
|
182 |
+
# Specify model
|
183 |
+
source_language = data['sourceLanguage']
|
184 |
+
target_language = data['targetLanguage']
|
185 |
+
#model = data['model']
|
186 |
+
# Define the messages for the chat
|
187 |
+
api_key=os.getenv("SARVAM_API_KEY", "")
|
188 |
+
url = "https://api.sarvam.ai/translate"
|
189 |
+
|
190 |
+
payload = {
|
191 |
+
"input": prompt,
|
192 |
+
"source_language_code": source_language,
|
193 |
+
"target_language_code": target_language,
|
194 |
+
"speaker_gender": "Male",
|
195 |
+
"mode": "formal",
|
196 |
+
"model": "mayura:v1",
|
197 |
+
"enable_preprocessing": True
|
198 |
+
}
|
199 |
+
headers = {"Content-Type": "application/json",
|
200 |
+
'API-Subscription-Key': f"{api_key}"
|
201 |
+
}
|
202 |
+
|
203 |
+
response = requests.request("POST", url, json=payload, headers=headers)
|
204 |
+
content = response.text
|
205 |
+
#print(chat_response.choices[0].message.content)
|
206 |
+
# Return the content of the response
|
207 |
+
return Response({"response": content})
|
208 |
+
except Exception as e:
|
209 |
+
print(f"An error occurred: {e}")
|
210 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
211 |
+
|
212 |
+
class TextLLMView(APIView):
|
213 |
+
def post(self, request, format=None):
|
214 |
+
try:
|
215 |
+
data = request.data
|
216 |
+
|
217 |
+
isOnline = data['isOnline']
|
218 |
+
|
219 |
+
prompt = data['messages'][0]['prompt']
|
220 |
+
# Specify model
|
221 |
+
#model = "pixtral-12b-2409"
|
222 |
+
model = data['model']
|
223 |
+
# Define the messages for the chat
|
224 |
+
messages = [
|
225 |
+
{
|
226 |
+
"role": "user",
|
227 |
+
"content": [
|
228 |
+
{
|
229 |
+
"type": "text",
|
230 |
+
"text": prompt
|
231 |
+
}
|
232 |
+
]
|
233 |
+
}
|
234 |
+
]
|
235 |
+
|
236 |
+
if(isOnline):
|
237 |
+
api_key = os.environ["MISTRAL_API_KEY"]
|
238 |
+
|
239 |
+
# Initialize the Mistral client
|
240 |
+
client = Mistral(api_key=api_key)
|
241 |
+
|
242 |
+
|
243 |
+
# Get the chat response
|
244 |
+
chat_response = client.chat.complete(
|
245 |
+
model=model,
|
246 |
+
messages=messages
|
247 |
+
)
|
248 |
+
|
249 |
+
content = chat_response.choices[0].message.content
|
250 |
+
else:
|
251 |
+
content = "helloWorld"
|
252 |
+
|
253 |
+
#print(chat_response.choices[0].message.content)
|
254 |
+
# Return the content of the response
|
255 |
+
return Response({"response": content})
|
256 |
+
except Exception as e:
|
257 |
+
print(f"An error occurred: {e}")
|
258 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
259 |
+
|
260 |
+
class IndicLLMView(APIView):
|
261 |
+
def post(self, request, format=None):
|
262 |
+
try:
|
263 |
+
data = request.data
|
264 |
+
|
265 |
+
isOnline = data['isOnline']
|
266 |
+
|
267 |
+
print(isOnline)
|
268 |
+
prompt = data['messages'][0]['prompt']
|
269 |
+
# Specify model
|
270 |
+
#model = "pixtral-12b-2409"
|
271 |
+
model = data['model']
|
272 |
+
# Define the messages for the chat
|
273 |
+
|
274 |
+
client = Client(host='http://localhost:11434')
|
275 |
+
response = client.chat(
|
276 |
+
model=model,
|
277 |
+
messages=[{
|
278 |
+
"role": "user",
|
279 |
+
"content": prompt,
|
280 |
+
}],
|
281 |
+
)
|
282 |
+
|
283 |
+
# Extract the model's response about the image
|
284 |
+
response_text = response['message']['content'].strip()
|
285 |
+
|
286 |
+
#print(chat_response.choices[0].message.content)
|
287 |
+
# Return the content of the response
|
288 |
+
return Response({"response": response_text})
|
289 |
+
except Exception as e:
|
290 |
+
print(f"An error occurred: {e}")
|
291 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
292 |
+
|
293 |
+
class LlamaVisionView(APIView):
|
294 |
+
def post(self, request, format=None):
|
295 |
+
try:
|
296 |
+
data = request.data
|
297 |
+
|
298 |
+
print("gere")
|
299 |
+
|
300 |
+
image_data = (data['messages'][0]['image'][0])
|
301 |
+
prompt = data['messages'][0]['prompt']
|
302 |
+
# Specify model
|
303 |
+
#model = "pixtral-12b-2409"
|
304 |
+
model = data['model']
|
305 |
+
# Define the messages for the chat
|
306 |
+
|
307 |
+
# Define the messages for the chat
|
308 |
+
|
309 |
+
print("gere")
|
310 |
+
client = Client(host='http://localhost:21434')
|
311 |
+
response = client.chat(
|
312 |
+
model="x/llama3.2-vision:latest",
|
313 |
+
messages=[{
|
314 |
+
"role": "user",
|
315 |
+
"content": prompt,
|
316 |
+
"images": [image_data]
|
317 |
+
}],
|
318 |
+
)
|
319 |
+
|
320 |
+
print("gere")
|
321 |
+
# Extract the model's response about the image
|
322 |
+
response_text = response['message']['content'].strip()
|
323 |
+
|
324 |
+
print(response_text)
|
325 |
+
content = response_text
|
326 |
+
print("gere")
|
327 |
+
|
328 |
+
|
329 |
+
#print(chat_response.choices[0].message.content)
|
330 |
+
# Return the content of the response
|
331 |
+
return Response({"response": content})
|
332 |
+
except Exception as e:
|
333 |
+
print(f"An error occurred: {e}")
|
334 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
335 |
+
|
336 |
+
|
337 |
+
class VisionLLMView(APIView):
|
338 |
+
def post(self, request, format=None):
|
339 |
+
try:
|
340 |
+
data = request.data
|
341 |
+
api_key = os.environ["MISTRAL_API_KEY"]
|
342 |
+
|
343 |
+
# Initialize the Mistral client
|
344 |
+
client = Mistral(api_key=api_key)
|
345 |
+
|
346 |
+
image_data = (data['messages'][0]['image'][0])
|
347 |
+
prompt = data['messages'][0]['prompt']
|
348 |
+
# Specify model
|
349 |
+
#model = "pixtral-12b-2409"
|
350 |
+
model = data['model']
|
351 |
+
# Define the messages for the chat
|
352 |
+
messages = [
|
353 |
+
{
|
354 |
+
"role": "user",
|
355 |
+
"content": [
|
356 |
+
{
|
357 |
+
"type": "text",
|
358 |
+
"text": prompt
|
359 |
+
},
|
360 |
+
{
|
361 |
+
"type": "image_url",
|
362 |
+
"image_url": f"data:image/jpeg;base64,{image_data}"
|
363 |
+
}
|
364 |
+
]
|
365 |
+
}
|
366 |
+
]
|
367 |
+
|
368 |
+
# Get the chat response
|
369 |
+
chat_response = client.chat.complete(
|
370 |
+
model=model,
|
371 |
+
messages=messages
|
372 |
+
)
|
373 |
+
|
374 |
+
content = chat_response.choices[0].message.content
|
375 |
+
#print(chat_response.choices[0].message.content)
|
376 |
+
# Return the content of the response
|
377 |
+
return Response({"response": content})
|
378 |
+
except Exception as e:
|
379 |
+
print(f"An error occurred: {e}")
|
380 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
381 |
+
|
382 |
+
|
383 |
+
class NIMVisionLLMView(APIView):
|
384 |
+
def post(self, request, format=None):
|
385 |
+
try:
|
386 |
+
invoke_url = "https://ai.api.nvidia.com/v1/gr/meta/llama-3.2-11b-vision-instruct/chat/completions"
|
387 |
+
stream = False
|
388 |
+
api_key = os.environ["NIM_API_KEY"]
|
389 |
+
data = request.data
|
390 |
+
model = data['model']
|
391 |
+
print(model)
|
392 |
+
image_data = (data['messages'][0]['image'][0])
|
393 |
+
prompt = data['messages'][0]['prompt']
|
394 |
+
headers = {
|
395 |
+
"Authorization": f"Bearer {api_key}",
|
396 |
+
"Accept": "text/event-stream" if stream else "application/json"
|
397 |
+
}
|
398 |
+
payload = {
|
399 |
+
"model": model,
|
400 |
+
"messages": [
|
401 |
+
{
|
402 |
+
"role": "user",
|
403 |
+
"content": f'{prompt} <img src="data:image/png;base64,{image_data}" />'
|
404 |
+
}
|
405 |
+
],
|
406 |
+
"max_tokens": 512,
|
407 |
+
"temperature": 1.00,
|
408 |
+
"top_p": 1.00,
|
409 |
+
"stream": stream
|
410 |
+
}
|
411 |
+
response = requests.post(invoke_url, headers=headers, json=payload)
|
412 |
+
|
413 |
+
if stream:
|
414 |
+
for line in response.iter_lines():
|
415 |
+
if line:
|
416 |
+
#print(line.decode("utf-8"))
|
417 |
+
data = line.decode("utf-8")
|
418 |
+
#content = json.loads(data)['choices'][0]['delta'].get('content', '')
|
419 |
+
else:
|
420 |
+
#print(response.json())
|
421 |
+
data = response.json()
|
422 |
+
content = data['choices'][0]['message']['content']
|
423 |
+
|
424 |
+
#print(content)
|
425 |
+
return Response({"response": content})
|
426 |
+
|
427 |
+
|
428 |
+
except Exception as e: # Added general exception handling
|
429 |
+
print(f"An error occurred: {e}")
|
430 |
+
return Response({'error': 'Something went wrong'}, status=500)
|
recipes/urls.py
CHANGED
@@ -1,17 +1,6 @@
|
|
1 |
from django.urls import path
|
2 |
from .views import recipe_generate_route
|
3 |
-
from .views import VisionLLMView, NIMVisionLLMView, TextLLMView, TranslateLLMView, SpeechLLMView, LlamaVisionView, IndicLLMView, TTSView, SpeechASRView, SpeechToSpeechView
|
4 |
|
5 |
urlpatterns = [
|
6 |
path('recipe_generate/', recipe_generate_route, name='recipe_generate'),
|
7 |
-
path('vision_llm_url/', VisionLLMView.as_view()),
|
8 |
-
path('nim_vision_llm_url/', NIMVisionLLMView.as_view()),
|
9 |
-
path('text_llm_url/', TextLLMView.as_view()),
|
10 |
-
path('translate_llm_url/', TranslateLLMView.as_view()),
|
11 |
-
path('speech_llm_url/', SpeechLLMView.as_view()),
|
12 |
-
path('speech_asr_url/', SpeechASRView.as_view()),
|
13 |
-
path('llama_vision_url/', LlamaVisionView.as_view()),
|
14 |
-
path('indic_llm_url/', IndicLLMView.as_view()),
|
15 |
-
path('tts_url/', TTSView.as_view()),
|
16 |
-
path('speech_to_speech_url/', SpeechToSpeechView.as_view()),
|
17 |
]
|
|
|
1 |
from django.urls import path
|
2 |
from .views import recipe_generate_route
|
|
|
3 |
|
4 |
urlpatterns = [
|
5 |
path('recipe_generate/', recipe_generate_route, name='recipe_generate'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
]
|