diff --git a/Dockerfile b/Dockerfile index d548409661b4e637f7414828e1c17e86b4478900..b3da5f370c20f0bb468e71786e2c2d93a499fa49 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,5 @@ # pull official base image -FROM python:3.10-bullseye - +FROM python:3.12-bullseye RUN useradd -m -u 1000 user USER user @@ -26,7 +25,6 @@ RUN pip install --no-cache-dir --upgrade -r requirements.txt COPY --chown=user . /app RUN python manage.py migrate - CMD ["python", "manage.py", "runserver", "0.0.0.0:7860"] #CMD ["uvicorn", "spaces.asgi:application", "--host", "0.0.0.0", "--port", "7860"] \ No newline at end of file diff --git a/dashboard/__init__.py b/dashboard/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/dashboard/admin.py b/dashboard/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..47aaf9a81cb67e6edc560f2fd03779557798c26a --- /dev/null +++ b/dashboard/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +# Register your models here. +from django.contrib import admin +from .models import Country + +admin.site.register(Country) \ No newline at end of file diff --git a/dashboard/apps.py b/dashboard/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..7b1cc053ac6a6ab71e1104a691564c4bb933e6b7 --- /dev/null +++ b/dashboard/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class DashboardConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'dashboard' diff --git a/dashboard/commands/generate_companies.py b/dashboard/commands/generate_companies.py new file mode 100644 index 0000000000000000000000000000000000000000..8f3d9cf90c6b3185c2fb7c690702bca00636455c --- /dev/null +++ b/dashboard/commands/generate_companies.py @@ -0,0 +1,32 @@ +import random +from django.core.management.base import BaseCommand +from dashboard.models import Country, Company + + +class Command(BaseCommand): + help = "Generate random companies for all countries" + + def handle(self, *args, **kwargs): + company_names = [ + "Global Tech Inc.", "Alpha Industries", "Beta Solutions", "Delta Corp.", + "Zeta Enterprises", "Omega Systems", "Apollo Holdings", "Titan Innovations" + ] + + for country in Country.objects.all(): + self.stdout.write(f"Generating companies for {country.name}...") + for _ in range(random.randint(3, 6)): # Generate 3-6 companies per country + Company.objects.create( + name=random.choice(company_names), + country=country, + balance_sheet={ + "Aktiva": { + "Anlagevermögen": random.randint(100000, 500000), + "Umlaufvermögen": random.randint(50000, 200000) + }, + "Passiva": { + "Eigenkapital": random.randint(70000, 300000), + "Fremdkapital": random.randint(20000, 150000) + } + } + ) + self.stdout.write(self.style.SUCCESS("Companies successfully generated!")) diff --git a/dashboard/commands/load_coordinates.py b/dashboard/commands/load_coordinates.py new file mode 100644 index 0000000000000000000000000000000000000000..f19573c86d9f93dcf02bdb572e2973340f466e75 --- /dev/null +++ b/dashboard/commands/load_coordinates.py @@ -0,0 +1,26 @@ +import json +from django.core.management.base import BaseCommand +from dashboard.models import Country + +class Command(BaseCommand): + help = "Load country data into the database" + + def handle(self, *args, **kwargs): + data = [ + {"name": "Germany", "iso_code": "DE", "latitude": 51.1657, "longitude": 10.4515, "pillar2_implemented": True, "local_top_up_tax": True}, + {"name": "France", "iso_code": "FR", "latitude": 46.6034, "longitude": 1.8883, "pillar2_implemented": True, "local_top_up_tax": False}, + {"name": "United States", "iso_code": "US", "latitude": 37.0902, "longitude": -95.7129, "pillar2_implemented": False, "local_top_up_tax": False}, + {"name": "Japan", "iso_code": "JP", "latitude": 36.2048, "longitude": 138.2529, "pillar2_implemented": True, "local_top_up_tax": True}, + {"name": "India", "iso_code": "IN", "latitude": 20.5937, "longitude": 78.9629, "pillar2_implemented": False, "local_top_up_tax": False} + ] + + for country_data in data: + country, created = Country.objects.get_or_create( + name=country_data["name"], + iso_code=country_data["iso_code"], + latitude=country_data["latitude"], + longitude=country_data["longitude"], + pillar2_implemented=country_data["pillar2_implemented"], + local_top_up_tax=country_data["local_top_up_tax"] + ) + self.stdout.write(f"{'Created' if created else 'Updated'}: {country.name}") \ No newline at end of file diff --git a/dashboard/commands/populate_country_data.py b/dashboard/commands/populate_country_data.py new file mode 100644 index 0000000000000000000000000000000000000000..1d0134345e5c14920b03eea71c4de19283ab99d9 --- /dev/null +++ b/dashboard/commands/populate_country_data.py @@ -0,0 +1,47 @@ +from django.core.management.base import BaseCommand +from dashboard.models import Country, CountryData +import random + +class Command(BaseCommand): + help = 'Populate CountryData with random balance sheet values' + + def handle(self, *args, **kwargs): + countries = Country.objects.all() + for country in countries: + for year in range(2020, 2025): # Add data for multiple years + balance_sheet = { + "Aktiva": { + "Anlagevermögen": { + "Sachanlagen": random.randint(10000, 50000), + "immaterielle Vermögensgegenstände": random.randint(5000, 20000), + "Finanzanlagen": random.randint(20000, 70000), + }, + "Umlaufvermögen": { + "Vorräte": random.randint(3000, 15000), + "Forderungen": random.randint(5000, 25000), + "Kassenbestand": random.randint(1000, 5000), + "Wertpapiere": random.randint(10000, 20000), + } + }, + "Passiva": { + "Eigenkapital": { + "Gezeichnetes Kapital": random.randint(50000, 100000), + "Kapitalrücklagen": random.randint(10000, 50000), + "Gewinnrücklagen": random.randint(20000, 60000), + }, + "Fremdkapital": { + "Kurzfristige Verbindlichkeiten": random.randint(10000, 40000), + "langfristige Verbindlichkeiten": random.randint(30000, 80000), + } + } + } + + CountryData.objects.create( + country=country, + year=year, + balance_sheet=balance_sheet, + company_name=f"Example Company {year}", + is_plausible=random.choice([True, False]) + ) + + self.stdout.write(self.style.SUCCESS("Successfully populated CountryData")) \ No newline at end of file diff --git a/dashboard/management/commands/generate_companies.py b/dashboard/management/commands/generate_companies.py new file mode 100644 index 0000000000000000000000000000000000000000..8f3d9cf90c6b3185c2fb7c690702bca00636455c --- /dev/null +++ b/dashboard/management/commands/generate_companies.py @@ -0,0 +1,32 @@ +import random +from django.core.management.base import BaseCommand +from dashboard.models import Country, Company + + +class Command(BaseCommand): + help = "Generate random companies for all countries" + + def handle(self, *args, **kwargs): + company_names = [ + "Global Tech Inc.", "Alpha Industries", "Beta Solutions", "Delta Corp.", + "Zeta Enterprises", "Omega Systems", "Apollo Holdings", "Titan Innovations" + ] + + for country in Country.objects.all(): + self.stdout.write(f"Generating companies for {country.name}...") + for _ in range(random.randint(3, 6)): # Generate 3-6 companies per country + Company.objects.create( + name=random.choice(company_names), + country=country, + balance_sheet={ + "Aktiva": { + "Anlagevermögen": random.randint(100000, 500000), + "Umlaufvermögen": random.randint(50000, 200000) + }, + "Passiva": { + "Eigenkapital": random.randint(70000, 300000), + "Fremdkapital": random.randint(20000, 150000) + } + } + ) + self.stdout.write(self.style.SUCCESS("Companies successfully generated!")) diff --git a/dashboard/management/commands/load_coordinates.py b/dashboard/management/commands/load_coordinates.py new file mode 100644 index 0000000000000000000000000000000000000000..f19573c86d9f93dcf02bdb572e2973340f466e75 --- /dev/null +++ b/dashboard/management/commands/load_coordinates.py @@ -0,0 +1,26 @@ +import json +from django.core.management.base import BaseCommand +from dashboard.models import Country + +class Command(BaseCommand): + help = "Load country data into the database" + + def handle(self, *args, **kwargs): + data = [ + {"name": "Germany", "iso_code": "DE", "latitude": 51.1657, "longitude": 10.4515, "pillar2_implemented": True, "local_top_up_tax": True}, + {"name": "France", "iso_code": "FR", "latitude": 46.6034, "longitude": 1.8883, "pillar2_implemented": True, "local_top_up_tax": False}, + {"name": "United States", "iso_code": "US", "latitude": 37.0902, "longitude": -95.7129, "pillar2_implemented": False, "local_top_up_tax": False}, + {"name": "Japan", "iso_code": "JP", "latitude": 36.2048, "longitude": 138.2529, "pillar2_implemented": True, "local_top_up_tax": True}, + {"name": "India", "iso_code": "IN", "latitude": 20.5937, "longitude": 78.9629, "pillar2_implemented": False, "local_top_up_tax": False} + ] + + for country_data in data: + country, created = Country.objects.get_or_create( + name=country_data["name"], + iso_code=country_data["iso_code"], + latitude=country_data["latitude"], + longitude=country_data["longitude"], + pillar2_implemented=country_data["pillar2_implemented"], + local_top_up_tax=country_data["local_top_up_tax"] + ) + self.stdout.write(f"{'Created' if created else 'Updated'}: {country.name}") \ No newline at end of file diff --git a/dashboard/management/commands/populate_country_data.py b/dashboard/management/commands/populate_country_data.py new file mode 100644 index 0000000000000000000000000000000000000000..1d0134345e5c14920b03eea71c4de19283ab99d9 --- /dev/null +++ b/dashboard/management/commands/populate_country_data.py @@ -0,0 +1,47 @@ +from django.core.management.base import BaseCommand +from dashboard.models import Country, CountryData +import random + +class Command(BaseCommand): + help = 'Populate CountryData with random balance sheet values' + + def handle(self, *args, **kwargs): + countries = Country.objects.all() + for country in countries: + for year in range(2020, 2025): # Add data for multiple years + balance_sheet = { + "Aktiva": { + "Anlagevermögen": { + "Sachanlagen": random.randint(10000, 50000), + "immaterielle Vermögensgegenstände": random.randint(5000, 20000), + "Finanzanlagen": random.randint(20000, 70000), + }, + "Umlaufvermögen": { + "Vorräte": random.randint(3000, 15000), + "Forderungen": random.randint(5000, 25000), + "Kassenbestand": random.randint(1000, 5000), + "Wertpapiere": random.randint(10000, 20000), + } + }, + "Passiva": { + "Eigenkapital": { + "Gezeichnetes Kapital": random.randint(50000, 100000), + "Kapitalrücklagen": random.randint(10000, 50000), + "Gewinnrücklagen": random.randint(20000, 60000), + }, + "Fremdkapital": { + "Kurzfristige Verbindlichkeiten": random.randint(10000, 40000), + "langfristige Verbindlichkeiten": random.randint(30000, 80000), + } + } + } + + CountryData.objects.create( + country=country, + year=year, + balance_sheet=balance_sheet, + company_name=f"Example Company {year}", + is_plausible=random.choice([True, False]) + ) + + self.stdout.write(self.style.SUCCESS("Successfully populated CountryData")) \ No newline at end of file diff --git a/dashboard/migrations/0001_initial.py b/dashboard/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..ef54fab4057eaf43110465d3dcab49b68a9f5646 --- /dev/null +++ b/dashboard/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 5.1.3 on 2024-11-24 10:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Country', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('iso_code', models.CharField(max_length=3, unique=True)), + ('gdp', models.DecimalField(blank=True, decimal_places=2, max_digits=15, null=True)), + ('effective_tax_rate', models.DecimalField(blank=True, decimal_places=2, max_digits=5, null=True)), + ('part_of_pillar2', models.BooleanField(default=False)), + ('latitude', models.FloatField(blank=True, null=True)), + ('longitude', models.FloatField(blank=True, null=True)), + ], + ), + ] diff --git a/dashboard/migrations/0002_remove_country_effective_tax_rate_remove_country_gdp_and_more.py b/dashboard/migrations/0002_remove_country_effective_tax_rate_remove_country_gdp_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..1c2da570ab7b034a5bccdd5fd980c449dbb70b36 --- /dev/null +++ b/dashboard/migrations/0002_remove_country_effective_tax_rate_remove_country_gdp_and_more.py @@ -0,0 +1,46 @@ +# Generated by Django 5.1.3 on 2024-11-24 11:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dashboard', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='country', + name='effective_tax_rate', + ), + migrations.RemoveField( + model_name='country', + name='gdp', + ), + migrations.AddField( + model_name='country', + name='local_top_up_tax', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='country', + name='pillar2_implemented', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='country', + name='iso_code', + field=models.CharField(max_length=10), + ), + migrations.AlterField( + model_name='country', + name='latitude', + field=models.FloatField(), + ), + migrations.AlterField( + model_name='country', + name='longitude', + field=models.FloatField(), + ), + ] diff --git a/dashboard/migrations/0003_countrydata_questionnaire.py b/dashboard/migrations/0003_countrydata_questionnaire.py new file mode 100644 index 0000000000000000000000000000000000000000..cf8051cd4bcca6e00130232cecd5511bb25ca611 --- /dev/null +++ b/dashboard/migrations/0003_countrydata_questionnaire.py @@ -0,0 +1,39 @@ +# Generated by Django 5.1.3 on 2024-11-24 14:29 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dashboard', '0002_remove_country_effective_tax_rate_remove_country_gdp_and_more'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='CountryData', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('year', models.IntegerField()), + ('balance_sheet', models.TextField()), + ('company_name', models.CharField(max_length=200)), + ('is_plausible', models.BooleanField(default=True)), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='data', to='dashboard.country')), + ], + ), + migrations.CreateModel( + name='Questionnaire', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('question', models.TextField()), + ('response', models.TextField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('is_resolved', models.BooleanField(default=False)), + ('country_data', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questionnaires', to='dashboard.countrydata')), + ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/dashboard/migrations/0004_alter_countrydata_balance_sheet_and_more.py b/dashboard/migrations/0004_alter_countrydata_balance_sheet_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..e19b8b8e5db994cb997f9844891050fe0ed27e19 --- /dev/null +++ b/dashboard/migrations/0004_alter_countrydata_balance_sheet_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 5.1.3 on 2024-11-24 15:07 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dashboard', '0003_countrydata_questionnaire'), + ] + + operations = [ + migrations.AlterField( + model_name='countrydata', + name='balance_sheet', + field=models.JSONField(default=dict), + ), + migrations.AlterField( + model_name='countrydata', + name='company_name', + field=models.CharField(max_length=255), + ), + migrations.AlterField( + model_name='countrydata', + name='country', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dashboard.country'), + ), + migrations.CreateModel( + name='Company', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('balance_sheet', models.JSONField()), + ('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='companies', to='dashboard.country')), + ], + ), + ] diff --git a/dashboard/migrations/__init__.py b/dashboard/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/dashboard/models.py b/dashboard/models.py new file mode 100644 index 0000000000000000000000000000000000000000..f63301277739b4ea312ee95890ddd94db9f43068 --- /dev/null +++ b/dashboard/models.py @@ -0,0 +1,43 @@ +from django.contrib.auth.models import User +from django.db import models + +class Country(models.Model): + name = models.CharField(max_length=100) + iso_code = models.CharField(max_length=10) + latitude = models.FloatField() + longitude = models.FloatField() + part_of_pillar2 = models.BooleanField(default=False) + pillar2_implemented = models.BooleanField(default=False) # Neu + local_top_up_tax = models.BooleanField(default=False) # Neu + + def __str__(self): + return self.name + +class CountryData(models.Model): + country = models.ForeignKey(Country, on_delete=models.CASCADE) + year = models.IntegerField() + balance_sheet = models.JSONField(default=dict) # JSONField for structured data + company_name = models.CharField(max_length=255) + is_plausible = models.BooleanField(default=True) + + def __str__(self): + return f"{self.country.name} - {self.year}" + +class Questionnaire(models.Model): + country_data = models.ForeignKey(CountryData, on_delete=models.CASCADE, related_name='questionnaires') + question = models.TextField() + response = models.TextField(blank=True, null=True) + created_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) + created_at = models.DateTimeField(auto_now_add=True) + is_resolved = models.BooleanField(default=False) + + def __str__(self): + return f"Questionnaire for {self.country_data.country.name} ({self.country_data.year})" + +class Company(models.Model): + name = models.CharField(max_length=200) + country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='companies') + balance_sheet = models.JSONField() # JSONField to store Aktiva/Passiva data + + def __str__(self): + return self.name \ No newline at end of file diff --git a/dashboard/static/css/style.css b/dashboard/static/css/style.css new file mode 100644 index 0000000000000000000000000000000000000000..9b3900c747f785fda99cb8f1523718fd1262fa75 --- /dev/null +++ b/dashboard/static/css/style.css @@ -0,0 +1,137 @@ +/* style.css */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Roboto', sans-serif; + background-color: #f4f8ff; /* Helles Blau als Hintergrund */ + color: #333; +} + +.hero { + background-color: #007bb5; /* Blau-Ton für den Hero-Bereich */ + color: white; + text-align: center; + padding: 100px 0; + border-bottom: 5px solid #006699; /* Dunklerer Blau-Ton als Trennung */ +} + +.hero h1 { + font-size: 3em; + margin-bottom: 20px; +} + +.hero p { + font-size: 1.2em; + margin-bottom: 30px; +} + +.cta-button { + background-color: #00aaff; /* Hellerer Blau-Ton für Button */ + color: white; + padding: 10px 20px; + text-decoration: none; + font-size: 1.1em; + border-radius: 5px; + margin-top: 20px; +} + +.cta-button:hover { + background-color: #0099cc; /* Dunklerer Blau-Ton für Hover */ +} + +.links { + margin-top: 30px; +} + +.link-item { + color: #00aaff; + font-size: 1.1em; + text-decoration: none; + margin-right: 20px; +} + +.link-item:hover { + text-decoration: underline; +} + +.features { + padding: 50px 20px; + text-align: center; + background-color: #e1efff; /* Leichterer Blauton für Features-Sektion */ +} + +.features h2 { + font-size: 2.5em; + margin-bottom: 40px; +} + +.feature { + background-color: white; + padding: 20px; + margin: 20px 0; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + border-radius: 8px; +} + +.feature h3 { + font-size: 1.5em; + margin-bottom: 10px; +} + +.feature p { + font-size: 1em; + color: #555; +} +/* Configuration Section Styling */ +.configuration { + background-color: #f4f8ff; /* Blau-Ton für den Hintergrund */ + color: #333; + text-align: center; /* Den Text zentrieren, wenn es ein zentrierter Header sein soll */ + padding: 80px 0; /* Etwas weniger Padding, damit mehr Platz für den Text bleibt */ + border-bottom: 5px solid #006699; /* Dunklerer Blau-Ton als Trennung */ +} + +/* Container innerhalb der Section */ +.configuration .container { + max-width: 1200px; /* Maximale Breite für die Container */ + margin: 0 auto; /* Zentriert den Container */ + padding: 0 15px; /* Leichter Abstand zu den Rändern */ +} + +/* Stil für die Überschrift */ +.configuration h1 { + font-size: 3em; /* Größere Schriftgröße für den Titel */ + margin-bottom: 20px; /* Abstand unter der Überschrift */ + line-height: 1.2; /* Zeilenhöhe für bessere Lesbarkeit */ +} + +/* Stil für die CTA-Schaltfläche */ +.cta-button { + background-color: #00aaff; /* Hellerer Blau-Ton für den Button */ + color: white; + padding: 15px 30px; /* Mehr Padding für die Schaltfläche */ + text-decoration: none; + font-size: 1.2em; /* Etwas größere Schriftgröße für bessere Sichtbarkeit */ + border-radius: 5px; + margin-top: 20px; + display: inline-block; /* Der Button wird als Inline-Block angezeigt, damit er nicht die gesamte Zeile ausfüllt */ +} + +.cta-button:hover { + background-color: #0099cc; /* Dunklerer Blau-Ton für Hover-Effekt */ +} + +footer { + background-color: #007bb5; /* Gleicher Blau-Ton wie im Hero-Bereich */ + color: white; + text-align: center; + padding: 20px; +} + +footer p { + font-size: 1em; +} \ No newline at end of file diff --git a/dashboard/static/js/map.js b/dashboard/static/js/map.js new file mode 100644 index 0000000000000000000000000000000000000000..8414163ca8fa3a95580cddabfce57f13c2bad36e --- /dev/null +++ b/dashboard/static/js/map.js @@ -0,0 +1,71 @@ +/*const countries = [ + { + name: "Germany", + iso_code: "DE", + latitude: 51.1657, + longitude: 10.4515, + pillar2_implemented: true, + local_top_up_tax: true + }, + { + name: "France", + iso_code: "FR", + latitude: 46.6034, + longitude: 1.8883, + pillar2_implemented: true, + local_top_up_tax: false + }, + { + name: "United States", + iso_code: "US", + latitude: 37.0902, + longitude: -95.7129, + pillar2_implemented: false, + local_top_up_tax: false + }, + { + name: "Japan", + iso_code: "JP", + latitude: 36.2048, + longitude: 138.2529, + pillar2_implemented: true, + local_top_up_tax: true + }, + { + name: "India", + iso_code: "IN", + latitude: 20.5937, + longitude: 78.9629, + pillar2_implemented: false, + local_top_up_tax: false + } +]; +*/ +// Initialize map +const map = L.map('map').setView([20, 0], 2); + +// Add OpenStreetMap tiles +L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19 +}).addTo(map); + +// Add countries to map +countries.forEach(country => { + const color = country.pillar2_implemented ? 'green' : 'gray'; + + // Add circle marker for each country + L.circleMarker([country.latitude, country.longitude], { + color: color, + radius: 10 + }).addTo(map).bindPopup(`${country.name}`); + + // Add symbol for Local Top-Up Tax + if (country.local_top_up_tax) { + L.marker([country.latitude, country.longitude], { + icon: L.divIcon({ + className: 'custom-icon', + html: '+' + }) + }).addTo(map); + } +}); \ No newline at end of file diff --git a/dashboard/templates/dashboard/aiAgent.html b/dashboard/templates/dashboard/aiAgent.html new file mode 100644 index 0000000000000000000000000000000000000000..932572119fffee02a5944a3766d7358e2c508791 --- /dev/null +++ b/dashboard/templates/dashboard/aiAgent.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/dashboard/templates/dashboard/company_detail.html b/dashboard/templates/dashboard/company_detail.html new file mode 100644 index 0000000000000000000000000000000000000000..ea4844d5d2172d16d48c1c22028764110e3bfd7c --- /dev/null +++ b/dashboard/templates/dashboard/company_detail.html @@ -0,0 +1,34 @@ + +{% load static %} + + + + + + {{ company.name }} - Details + + +
+

{{ company.name }}

+

Details for {{ company.name }} in {{ company.country.name }}

+
+
+

Financial Data

+
+

Aktiva

+ +

Passiva

+ +
+
+ + + \ No newline at end of file diff --git a/dashboard/templates/dashboard/connectors.html b/dashboard/templates/dashboard/connectors.html new file mode 100644 index 0000000000000000000000000000000000000000..932572119fffee02a5944a3766d7358e2c508791 --- /dev/null +++ b/dashboard/templates/dashboard/connectors.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/dashboard/templates/dashboard/country_detail.html b/dashboard/templates/dashboard/country_detail.html new file mode 100644 index 0000000000000000000000000000000000000000..2bb009363038babaa8567268c6a14ae4dd19e67a --- /dev/null +++ b/dashboard/templates/dashboard/country_detail.html @@ -0,0 +1,105 @@ + +{% load static %} + + + + + + {{ country.name }} - {{ data.year }} + + +
+

{{ country.name }} - {{ data.year }}

+

Details for {{ data.company_name }}

+
+
+

Financial Data

+
+

Balance Sheet: {{ data.balance_sheet }}

+

Plausibility: {% if data.is_plausible %}✔️ Plausible{% else %}❌ Implausible{% endif %}

+
+ +

Actions

+ +

Send Questionnaire

+
+ + +
+
+

Balance Sheet

+
+

Aktiva

+ +

Passiva

+ +
+ + + + diff --git a/dashboard/templates/dashboard/country_list.html b/dashboard/templates/dashboard/country_list.html new file mode 100644 index 0000000000000000000000000000000000000000..204ed5ead324bebb1e2fe54ceba85eeff68e033e --- /dev/null +++ b/dashboard/templates/dashboard/country_list.html @@ -0,0 +1,41 @@ + +{% load static %} + + + + + + Country Overview + + +
+

Country Overview

+

Explore financial data for each company by country

+
+
+

Available Countries and Companies

+
+ + +
+

© 2024 Pillar 2 Dashboard

+
+ + \ No newline at end of file diff --git a/dashboard/templates/dashboard/dashboard.html b/dashboard/templates/dashboard/dashboard.html new file mode 100644 index 0000000000000000000000000000000000000000..8f11975e580dbda656e1e8b7ad3fc7d0d62c61ba --- /dev/null +++ b/dashboard/templates/dashboard/dashboard.html @@ -0,0 +1,267 @@ + + + + + + Pillar 2 Dashboard + + + + +

Pillar 2 Dashboard

+
+ + + \ No newline at end of file diff --git a/dashboard/templates/dashboard/masterData.html b/dashboard/templates/dashboard/masterData.html new file mode 100644 index 0000000000000000000000000000000000000000..932572119fffee02a5944a3766d7358e2c508791 --- /dev/null +++ b/dashboard/templates/dashboard/masterData.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/dashboard/templates/dashboard/start_page.html b/dashboard/templates/dashboard/start_page.html new file mode 100644 index 0000000000000000000000000000000000000000..4af0758a97dbb4af27625e023663bbb9780b05c2 --- /dev/null +++ b/dashboard/templates/dashboard/start_page.html @@ -0,0 +1,61 @@ + +{% load static %} + + + + + Your Tax-Cockpit + + + + +
+
+

Your Tax-Cockpit

+

Get an overview about our functions

+ Show a Pillar 2 overview Map +
+ +
+ +
+
+

Configuration

+ Add your Master-Data + +
+ + + + + + +
+ +
+
+

What We Offer

+
+

Connect your Systems

+

Keep your Data in one place

+

Modular dashboard, different use-cases can be added

+
+ +
+
+ +
+
+

© 2024 My Django Site. All Rights Reserved.

+
+
+ + \ No newline at end of file diff --git a/dashboard/templates/dashboard/userManagement.html b/dashboard/templates/dashboard/userManagement.html new file mode 100644 index 0000000000000000000000000000000000000000..932572119fffee02a5944a3766d7358e2c508791 --- /dev/null +++ b/dashboard/templates/dashboard/userManagement.html @@ -0,0 +1,10 @@ + + + + + Title + + + + + \ No newline at end of file diff --git a/dashboard/tests.py b/dashboard/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/dashboard/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/dashboard/urls.py b/dashboard/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..d89c6002e350f27ddfd0ef21d48f875af910e0dd --- /dev/null +++ b/dashboard/urls.py @@ -0,0 +1,24 @@ +from django.urls import path +from . import views +from .views import ( + StartPageView, + masterData, + connectors, + userManagement, + aiAgent,) + + +urlpatterns = [ + path('', StartPageView.as_view(), name='start_page'), # Startseite + path('overview', views.dashboard, name='dashboard'), # Dashboard + path('masterData', masterData, name='masterData'), # Master Data + path('connectors', connectors, name='connectors'), # Connectors + path('userManagement', userManagement, name='userManagement'), # User Management + path('aiAgent', aiAgent, name='aiAgent'), # AI Agent + path('countries/', views.country_list, name='country_list'), + path('countries///', views.country_detail, name='country_detail'), + path('mark_implausible//', views.mark_implausible, name='mark_implausible'), + path('send_questionnaire//', views.send_questionnaire, name='send_questionnaire'), + path('companies//', views.company_detail, name='company_detail'), + +] \ No newline at end of file diff --git a/dashboard/views.py b/dashboard/views.py new file mode 100644 index 0000000000000000000000000000000000000000..8757e2708864c058dd41b5aec3edd35bd0bace18 --- /dev/null +++ b/dashboard/views.py @@ -0,0 +1,82 @@ +from django.http import JsonResponse +from django.shortcuts import render, get_object_or_404 +from django.views.decorators.csrf import csrf_exempt +from django.shortcuts import render, get_object_or_404, redirect +from .models import Country, CountryData, Questionnaire +from django.http import JsonResponse +from django.views.decorators.csrf import csrf_exempt +from .models import Country +from django.views.generic import ListView, DetailView, CreateView, UpdateView, TemplateView + +class StartPageView(TemplateView): + template_name = "dashboard/start_page.html" + +def dashboard(request): + countries = Country.objects.all() + country_data = [ + { + "name": country.name, + "iso_code": country.iso_code, + "latitude": country.latitude, + "longitude": country.longitude, + "pillar2_implemented": country.pillar2_implemented, + "local_top_up_tax": country.local_top_up_tax, + } + for country in countries + ] + return render(request, 'dashboard/dashboard.html', {"countries": country_data}) + + +def country_list(request): + countries = Country.objects.all() + return render(request, 'dashboard/country_list.html', {'countries': countries}) + +def country_detail(request, country_id, year): + country = get_object_or_404(Country, id=country_id) + data = get_object_or_404(CountryData, country=country, year=year) + questionnaires = data.questionnaires.all() + return render(request, 'dashboard/country_detail.html', { + 'country': country, + 'data': data, + 'questionnaires': questionnaires, + }) + +@csrf_exempt +def mark_implausible(request, country_data_id): + if request.method == 'POST': + data = get_object_or_404(CountryData, id=country_data_id) + data.is_plausible = False + data.save() + return JsonResponse({'status': 'success'}) + +@csrf_exempt +def send_questionnaire(request, country_data_id): + if request.method == 'POST': + question = request.POST.get('question') + country_data = get_object_or_404(CountryData, id=country_data_id) + Questionnaire.objects.create( + country_data=country_data, + question=question, + created_by=request.user + ) + return JsonResponse({'status': 'questionnaire_created'}) + + +from django.shortcuts import render, get_object_or_404 +from .models import Company + +def company_detail(request, company_id): + company = get_object_or_404(Company, id=company_id) + return render(request, 'dashboard/company_detail.html', {"company": company}) + +def masterData(request): + return render(request, 'dashboard/masterData.html') + +def connectors(request): + return render(request, 'dashboard/connectors.html') + +def userManagement(request): + return render(request, 'dashboard/userManagement.html') + +def aiAgent(request): + return render(request, 'dashboard/aiAgent.html') diff --git a/docs/setup.md b/docs/setup.md deleted file mode 100644 index df4272bd3e5684b57a124e8c942194a71dcaeada..0000000000000000000000000000000000000000 --- a/docs/setup.md +++ /dev/null @@ -1,47 +0,0 @@ -Backend - -Setup - - - -git clone https://huggingface.co/spaces/gaganyatri/django_spaces - -cd django_spaces - -docker build -t slabstech/gaganyatri -f Dockerfile . - -docker run slabstech/gaganyatri - - -- Steps to build this project - - python3.10 -m venv venv - - source venv/bin/activate - - pip install Django==5.1.1 - - django-admin startproject spaces . - - python manage.py migrate - - python manage.py runserver - - - python manage.py startapp space_walks - - python manage.py makemigrations - - python manage.py migrate - - - - pip install uvicorn - - python -m uvicorn spaces.asgi:application - - -- Merge for Huggingface - - git fetch --all - - git checkout main - - git merge --squash django-setup - - git commit -m "merge" - - git push origin main - - - - - Referenc - - https://www.djangoproject.com/download/ - - https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/ - - https://github.com/testdrivenio/django-on-docker - - \ No newline at end of file diff --git a/games/__init__.py b/games/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/games/admin.py b/games/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8a45832ac104b79d66156766864e4b8d98190953 --- /dev/null +++ b/games/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Game + +admin.site.register(Game) diff --git a/games/apps.py b/games/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..1a3efecd74780eea04b23c15fb0f682ae555fd52 --- /dev/null +++ b/games/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class GamesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'games' diff --git a/games/migrations/0001_initial.py b/games/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..f6612ffbc44fa42fb5118eaffbbab4f7964554fb --- /dev/null +++ b/games/migrations/0001_initial.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.1 on 2024-10-31 09:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Game', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('description', models.TextField()), + ('release_date', models.DateField()), + ], + ), + ] diff --git a/games/migrations/__init__.py b/games/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/games/models.py b/games/models.py new file mode 100644 index 0000000000000000000000000000000000000000..33fc04a10ce3c54177c29f418c7d258a6bcf6ed6 --- /dev/null +++ b/games/models.py @@ -0,0 +1,6 @@ +from django.db import models + +class Game(models.Model): + name = models.CharField(max_length=200) + description = models.TextField() + release_date = models.DateField() diff --git a/games/templates/game_list.html b/games/templates/game_list.html new file mode 100644 index 0000000000000000000000000000000000000000..dfbde615285df5d6912f3715a42859b47987f3d0 --- /dev/null +++ b/games/templates/game_list.html @@ -0,0 +1,16 @@ + + + + Game List + + +

Games

+ {% for game in games %} +
  • +

    {{ game.name }}

    +

    {{ game.description }}

    +

    Released on: {{ game.release_date }}

    +
  • + {% endfor %} + + diff --git a/games/tests.py b/games/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/games/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/games/urls.py b/games/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..0605c8a194b4b6db94c2fd5dbe0d69c99404e7b0 --- /dev/null +++ b/games/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.game_list, name='game_list'), +] \ No newline at end of file diff --git a/games/views.py b/games/views.py new file mode 100644 index 0000000000000000000000000000000000000000..90cfd8de613408ae414b7ab94b959e14acd677ce --- /dev/null +++ b/games/views.py @@ -0,0 +1,6 @@ +from django.shortcuts import render +from .models import Game + +def game_list(request): + games = Game.objects.all() + return render(request, 'games/game_list.html', {'games': games}) diff --git a/inference/__init__.py b/inference/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/inference/admin.py b/inference/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/inference/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/inference/apps.py b/inference/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..8828545787b4be35ce31a85ea4d5be446dadcf91 --- /dev/null +++ b/inference/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class InferenceConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'inference' diff --git a/inference/migrations/__init__.py b/inference/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/inference/models.py b/inference/models.py new file mode 100644 index 0000000000000000000000000000000000000000..71a836239075aa6e6e4ecb700e9c42c95c022d91 --- /dev/null +++ b/inference/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/inference/tests.py b/inference/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/inference/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/inference/urls.py b/inference/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..b3f0a7186c618a19c3c06d2e2b3f509a65a71b59 --- /dev/null +++ b/inference/urls.py @@ -0,0 +1,15 @@ +from django.urls import path +from .views import VisionLLMView, NIMVisionLLMView, TextLLMView, TranslateLLMView, SpeechLLMView, LlamaVisionView, IndicLLMView, TTSView, SpeechASRView, SpeechToSpeechView + +urlpatterns = [ + path('vision_llm_url/', VisionLLMView.as_view()), + path('nim_vision_llm_url/', NIMVisionLLMView.as_view()), + path('text_llm_url/', TextLLMView.as_view()), + path('translate_llm_url/', TranslateLLMView.as_view()), + path('speech_llm_url/', SpeechLLMView.as_view()), + path('speech_asr_url/', SpeechASRView.as_view()), + path('llama_vision_url/', LlamaVisionView.as_view()), + path('indic_llm_url/', IndicLLMView.as_view()), + path('tts_url/', TTSView.as_view()), + path('speech_to_speech_url/', SpeechToSpeechView.as_view()), +] diff --git a/inference/views.py b/inference/views.py new file mode 100644 index 0000000000000000000000000000000000000000..be934c2ad38012a478b3888f75655d03f93b9393 --- /dev/null +++ b/inference/views.py @@ -0,0 +1,430 @@ +from django.http import JsonResponse +from rest_framework.response import Response +from rest_framework.views import APIView +from mistralai import Mistral +import os +import requests +from openai import OpenAI +from ollama import Client +from django.http import FileResponse +import io + +class TTSView(APIView): + def post(self, request, format=None): + # Define the API endpoint + # Define the URL for the TTS API + url = 'http://localhost:5002/api/tts' + + # Define the multiline text + text = "This is the first line" + + # Prepare the parameters for the GET request + params = { + 'text': text + } + + # Make the GET request + response = requests.get(url, params=params) + + # Check if the request was successful + if response.status_code == 200: + # Save the audio response as a WAV file + # Create a file-like object with the audio data + audio_data = io.BytesIO(response.content) + + # Return the audio file as a response + return FileResponse(audio_data, as_attachment=True, filename='audio_output.wav') + else: + return Response({"error": "Failed to synthesize speech"}, status=response.status_code) + +class SpeechASRView(APIView): + def post(self, request, format=None): + try: + data = request.data + ##prompt = data['prompt'] + audio = data['audio'] + print('hre1') + client = OpenAI(api_key="cant-be-empty", base_url="http://0.0.0.0:11800/v1/") + print('her2') + #filename= '/home/gaganyatri/Music/test1.flac' + audio_bytes = audio.read() + + #audio_file = open(filename, "rb") + + transcript = client.audio.transcriptions.create( + model="Systran/faster-distil-whisper-small.en", file=audio_bytes + ) + + #print(transcript.text) + voice_content = transcript.text + return Response({"response": voice_content}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + + +class SpeechToSpeechView(APIView): + def post(self, request, format=None): + try: + data = request.data + ##prompt = data['prompt'] + audio = data['audio'] + + client = OpenAI(api_key="cant-be-empty", base_url="http://0.0.0.0:11800/v1/") + + #filename= '/home/gaganyatri/Music/test1.flac' + audio_bytes = audio.read() + + #audio_file = open(filename, "rb") + + transcript = client.audio.transcriptions.create( + model="Systran/faster-distil-whisper-small.en", file=audio_bytes + ) + + #print(transcript.text) + voice_content = transcript.text + #content = 'audio recieved' + system_prompt = "Please summarize the following prompt into a concise and clear statement:" + + + model = "mistral-nemo:latest" + client = Client(host='http://localhost:11434') + response = client.chat( + model=model, + messages=[ + { + "role": "system", + "content": system_prompt + }, + { + "role": "user", + "content": voice_content, + } + ], + ) + + # Extract the model's response about the image + response_text = response['message']['content'].strip() + + url = 'http://localhost:5002/api/tts' + + # Define the multiline text + #text = "This is the first line" + + # Prepare the parameters for the GET request + params = { + 'text': response_text + } + + # Make the GET request + response = requests.get(url, params=params) + + # Check if the request was successful + if response.status_code == 200: + # Save the audio response as a WAV file + # Create a file-like object with the audio data + audio_data = io.BytesIO(response.content) + + # Return the audio file as a response + return FileResponse(audio_data, as_attachment=True, filename='audio_output.wav') + else: + return Response({"error": "Failed to synthesize speech"}, status=response.status_code) + + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + +class SpeechLLMView(APIView): + def post(self, request, format=None): + try: + data = request.data + ##prompt = data['prompt'] + audio = data['audio'] + + client = OpenAI(api_key="cant-be-empty", base_url="http://localhost:11800/v1/") + + #filename= '/home/gaganyatri/Music/test1.flac' + audio_bytes = audio.read() + + #audio_file = open(filename, "rb") + + transcript = client.audio.transcriptions.create( + model="Systran/faster-distil-whisper-small.en", file=audio_bytes + ) + + #print(transcript.text) + voice_content = transcript.text + #content = 'audio recieved' + + model = "mistral-nemo:latest" + client = Client(host='http://localhost:11434') + response = client.chat( + model=model, + messages=[{ + "role": "user", + "content": voice_content, + }], + ) + + # Extract the model's response about the image + response_text = response['message']['content'].strip() + + return Response({"response": response_text}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + +class TranslateLLMView(APIView): + def post(self, request, format=None): + try: + data = request.data + prompt = data['messages'][0]['prompt'] + # Specify model + source_language = data['sourceLanguage'] + target_language = data['targetLanguage'] + #model = data['model'] + # Define the messages for the chat + api_key=os.getenv("SARVAM_API_KEY", "") + url = "https://api.sarvam.ai/translate" + + payload = { + "input": prompt, + "source_language_code": source_language, + "target_language_code": target_language, + "speaker_gender": "Male", + "mode": "formal", + "model": "mayura:v1", + "enable_preprocessing": True + } + headers = {"Content-Type": "application/json", + 'API-Subscription-Key': f"{api_key}" + } + + response = requests.request("POST", url, json=payload, headers=headers) + content = response.text + #print(chat_response.choices[0].message.content) + # Return the content of the response + return Response({"response": content}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + +class TextLLMView(APIView): + def post(self, request, format=None): + try: + data = request.data + + isOnline = data['isOnline'] + + prompt = data['messages'][0]['prompt'] + # Specify model + #model = "pixtral-12b-2409" + model = data['model'] + # Define the messages for the chat + messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": prompt + } + ] + } + ] + + if(isOnline): + api_key = os.environ["MISTRAL_API_KEY"] + + # Initialize the Mistral client + client = Mistral(api_key=api_key) + + + # Get the chat response + chat_response = client.chat.complete( + model=model, + messages=messages + ) + + content = chat_response.choices[0].message.content + else: + content = "helloWorld" + + #print(chat_response.choices[0].message.content) + # Return the content of the response + return Response({"response": content}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + +class IndicLLMView(APIView): + def post(self, request, format=None): + try: + data = request.data + + isOnline = data['isOnline'] + + print(isOnline) + prompt = data['messages'][0]['prompt'] + # Specify model + #model = "pixtral-12b-2409" + model = data['model'] + # Define the messages for the chat + + client = Client(host='http://localhost:11434') + response = client.chat( + model=model, + messages=[{ + "role": "user", + "content": prompt, + }], + ) + + # Extract the model's response about the image + response_text = response['message']['content'].strip() + + #print(chat_response.choices[0].message.content) + # Return the content of the response + return Response({"response": response_text}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + +class LlamaVisionView(APIView): + def post(self, request, format=None): + try: + data = request.data + + print("gere") + + image_data = (data['messages'][0]['image'][0]) + prompt = data['messages'][0]['prompt'] + # Specify model + #model = "pixtral-12b-2409" + model = data['model'] + # Define the messages for the chat + + # Define the messages for the chat + + print("gere") + client = Client(host='http://localhost:21434') + response = client.chat( + model="x/llama3.2-vision:latest", + messages=[{ + "role": "user", + "content": prompt, + "images": [image_data] + }], + ) + + print("gere") + # Extract the model's response about the image + response_text = response['message']['content'].strip() + + print(response_text) + content = response_text + print("gere") + + + #print(chat_response.choices[0].message.content) + # Return the content of the response + return Response({"response": content}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + + +class VisionLLMView(APIView): + def post(self, request, format=None): + try: + data = request.data + api_key = os.environ["MISTRAL_API_KEY"] + + # Initialize the Mistral client + client = Mistral(api_key=api_key) + + image_data = (data['messages'][0]['image'][0]) + prompt = data['messages'][0]['prompt'] + # Specify model + #model = "pixtral-12b-2409" + model = data['model'] + # Define the messages for the chat + messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": prompt + }, + { + "type": "image_url", + "image_url": f"data:image/jpeg;base64,{image_data}" + } + ] + } + ] + + # Get the chat response + chat_response = client.chat.complete( + model=model, + messages=messages + ) + + content = chat_response.choices[0].message.content + #print(chat_response.choices[0].message.content) + # Return the content of the response + return Response({"response": content}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + + +class NIMVisionLLMView(APIView): + def post(self, request, format=None): + try: + invoke_url = "https://ai.api.nvidia.com/v1/gr/meta/llama-3.2-11b-vision-instruct/chat/completions" + stream = False + api_key = os.environ["NIM_API_KEY"] + data = request.data + model = data['model'] + print(model) + image_data = (data['messages'][0]['image'][0]) + prompt = data['messages'][0]['prompt'] + headers = { + "Authorization": f"Bearer {api_key}", + "Accept": "text/event-stream" if stream else "application/json" + } + payload = { + "model": model, + "messages": [ + { + "role": "user", + "content": f'{prompt} ' + } + ], + "max_tokens": 512, + "temperature": 1.00, + "top_p": 1.00, + "stream": stream + } + response = requests.post(invoke_url, headers=headers, json=payload) + + if stream: + for line in response.iter_lines(): + if line: + #print(line.decode("utf-8")) + data = line.decode("utf-8") + #content = json.loads(data)['choices'][0]['delta'].get('content', '') + else: + #print(response.json()) + data = response.json() + content = data['choices'][0]['message']['content'] + + #print(content) + return Response({"response": content}) + + + except Exception as e: # Added general exception handling + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) diff --git a/recipes/urls.py b/recipes/urls.py index 7fa417e14f6640082d022f48d77a1851237e33c6..a05cc2f2f9079d54f04bfd64e8092d985a37528a 100644 --- a/recipes/urls.py +++ b/recipes/urls.py @@ -1,17 +1,6 @@ from django.urls import path from .views import recipe_generate_route -from .views import VisionLLMView, NIMVisionLLMView, TextLLMView, TranslateLLMView, SpeechLLMView, LlamaVisionView, IndicLLMView, TTSView, SpeechASRView, SpeechToSpeechView urlpatterns = [ path('recipe_generate/', recipe_generate_route, name='recipe_generate'), - path('vision_llm_url/', VisionLLMView.as_view()), - path('nim_vision_llm_url/', NIMVisionLLMView.as_view()), - path('text_llm_url/', TextLLMView.as_view()), - path('translate_llm_url/', TranslateLLMView.as_view()), - path('speech_llm_url/', SpeechLLMView.as_view()), - path('speech_asr_url/', SpeechASRView.as_view()), - path('llama_vision_url/', LlamaVisionView.as_view()), - path('indic_llm_url/', IndicLLMView.as_view()), - path('tts_url/', TTSView.as_view()), - path('speech_to_speech_url/', SpeechToSpeechView.as_view()), ] diff --git a/recipes/views.py b/recipes/views.py index ec8d4cc389dfa89421a477e9d422a755b32e4fb8..6c6344f06335b9cec59d2d2e602a24e3b03ec095 100644 --- a/recipes/views.py +++ b/recipes/views.py @@ -1,302 +1,7 @@ -from django.http import JsonResponse from rest_framework.decorators import api_view from rest_framework.response import Response -from rest_framework import serializers from .engine import execute_prompt, bundle_function, propose_recipes, compute_reduced_prices -from rest_framework.views import APIView -from mistralai import Mistral -import os -import base64 import json -import requests -from openai import OpenAI -from ollama import Client -from django.http import FileResponse -import io - -class TTSView(APIView): - def post(self, request, format=None): - # Define the API endpoint - # Define the URL for the TTS API - url = 'http://localhost:5002/api/tts' - - # Define the multiline text - text = "This is the first line" - - # Prepare the parameters for the GET request - params = { - 'text': text - } - - # Make the GET request - response = requests.get(url, params=params) - - # Check if the request was successful - if response.status_code == 200: - # Save the audio response as a WAV file - # Create a file-like object with the audio data - audio_data = io.BytesIO(response.content) - - # Return the audio file as a response - return FileResponse(audio_data, as_attachment=True, filename='audio_output.wav') - else: - return Response({"error": "Failed to synthesize speech"}, status=response.status_code) - -class SpeechASRView(APIView): - def post(self, request, format=None): - try: - data = request.data - ##prompt = data['prompt'] - audio = data['audio'] - - client = OpenAI(api_key="cant-be-empty", base_url="http://localhost:11800/v1/") - - #filename= '/home/gaganyatri/Music/test1.flac' - audio_bytes = audio.read() - - #audio_file = open(filename, "rb") - - transcript = client.audio.transcriptions.create( - model="Systran/faster-distil-whisper-small.en", file=audio_bytes - ) - - #print(transcript.text) - voice_content = transcript.text - return Response({"response": voice_content}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - - -class SpeechToSpeechView(APIView): - def post(self, request, format=None): - try: - data = request.data - ##prompt = data['prompt'] - audio = data['audio'] - - client = OpenAI(api_key="cant-be-empty", base_url="http://localhost:11800/v1/") - - #filename= '/home/gaganyatri/Music/test1.flac' - audio_bytes = audio.read() - - #audio_file = open(filename, "rb") - - transcript = client.audio.transcriptions.create( - model="Systran/faster-distil-whisper-small.en", file=audio_bytes - ) - - #print(transcript.text) - voice_content = transcript.text - #content = 'audio recieved' - system_prompt = "Please summarize the following prompt into a concise and clear statement:" - - - model = "mistral-nemo:latest" - client = Client(host='http://localhost:11434') - response = client.chat( - model=model, - messages=[ - { - "role": "system", - "content": system_prompt - }, - { - "role": "user", - "content": voice_content, - } - ], - ) - - # Extract the model's response about the image - response_text = response['message']['content'].strip() - - url = 'http://localhost:5002/api/tts' - - # Define the multiline text - #text = "This is the first line" - - # Prepare the parameters for the GET request - params = { - 'text': response_text - } - - # Make the GET request - response = requests.get(url, params=params) - - # Check if the request was successful - if response.status_code == 200: - # Save the audio response as a WAV file - # Create a file-like object with the audio data - audio_data = io.BytesIO(response.content) - - # Return the audio file as a response - return FileResponse(audio_data, as_attachment=True, filename='audio_output.wav') - else: - return Response({"error": "Failed to synthesize speech"}, status=response.status_code) - - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - -class SpeechLLMView(APIView): - def post(self, request, format=None): - try: - data = request.data - ##prompt = data['prompt'] - audio = data['audio'] - - client = OpenAI(api_key="cant-be-empty", base_url="http://localhost:11800/v1/") - - #filename= '/home/gaganyatri/Music/test1.flac' - audio_bytes = audio.read() - - #audio_file = open(filename, "rb") - - transcript = client.audio.transcriptions.create( - model="Systran/faster-distil-whisper-small.en", file=audio_bytes - ) - - #print(transcript.text) - voice_content = transcript.text - #content = 'audio recieved' - - model = "mistral-nemo:latest" - client = Client(host='http://localhost:11434') - response = client.chat( - model=model, - messages=[{ - "role": "user", - "content": voice_content, - }], - ) - - # Extract the model's response about the image - response_text = response['message']['content'].strip() - - return Response({"response": response_text}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - -class TranslateLLMView(APIView): - def post(self, request, format=None): - try: - data = request.data - prompt = data['messages'][0]['prompt'] - # Specify model - source_language = data['sourceLanguage'] - target_language = data['targetLanguage'] - #model = data['model'] - # Define the messages for the chat - api_key=os.getenv("SARVAM_API_KEY", "") - url = "https://api.sarvam.ai/translate" - - payload = { - "input": prompt, - "source_language_code": source_language, - "target_language_code": target_language, - "speaker_gender": "Male", - "mode": "formal", - "model": "mayura:v1", - "enable_preprocessing": True - } - headers = {"Content-Type": "application/json", - 'API-Subscription-Key': f"{api_key}" - } - - response = requests.request("POST", url, json=payload, headers=headers) - content = response.text - #print(chat_response.choices[0].message.content) - # Return the content of the response - return Response({"response": content}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - -class TextLLMView(APIView): - def post(self, request, format=None): - try: - data = request.data - - isOnline = data['isOnline'] - - print(isOnline) - prompt = data['messages'][0]['prompt'] - # Specify model - #model = "pixtral-12b-2409" - model = data['model'] - # Define the messages for the chat - messages = [ - { - "role": "user", - "content": [ - { - "type": "text", - "text": prompt - } - ] - } - ] - - if(isOnline): - api_key = os.environ["MISTRAL_API_KEY"] - - # Initialize the Mistral client - client = Mistral(api_key=api_key) - - - # Get the chat response - chat_response = client.chat.complete( - model=model, - messages=messages - ) - - content = chat_response.choices[0].message.content - else: - content = "helloWorld" - - #print(chat_response.choices[0].message.content) - # Return the content of the response - return Response({"response": content}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - -class IndicLLMView(APIView): - def post(self, request, format=None): - try: - data = request.data - - isOnline = data['isOnline'] - - print(isOnline) - prompt = data['messages'][0]['prompt'] - # Specify model - #model = "pixtral-12b-2409" - model = data['model'] - # Define the messages for the chat - - client = Client(host='http://localhost:11434') - response = client.chat( - model=model, - messages=[{ - "role": "user", - "content": prompt, - }], - ) - - # Extract the model's response about the image - response_text = response['message']['content'].strip() - - #print(chat_response.choices[0].message.content) - # Return the content of the response - return Response({"response": response_text}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - - @api_view(['GET']) def recipe_generate_route(request): @@ -313,138 +18,3 @@ def recipe_generate_route(request): print(f"An error occurred: {e}") return Response({'error': 'Something went wrong'}, status=500) return Response(result) - - -class LlamaVisionView(APIView): - def post(self, request, format=None): - try: - data = request.data - - image_data = (data['messages'][0]['image'][0]) - prompt = data['messages'][0]['prompt'] - # Specify model - #model = "pixtral-12b-2409" - model = data['model'] - # Define the messages for the chat - - # Define the messages for the chat - - client = Client(host='http://localhost:21434') - response = client.chat( - model="x/llama3.2-vision:latest", - messages=[{ - "role": "user", - "content": prompt, - "images": [image_data] - }], - ) - - # Extract the model's response about the image - response_text = response['message']['content'].strip() - - print(response_text) - content = response_text - - - #print(chat_response.choices[0].message.content) - # Return the content of the response - return Response({"response": content}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - - -class VisionLLMView(APIView): - def post(self, request, format=None): - try: - data = request.data - api_key = os.environ["MISTRAL_API_KEY"] - - # Initialize the Mistral client - client = Mistral(api_key=api_key) - - image_data = (data['messages'][0]['image'][0]) - prompt = data['messages'][0]['prompt'] - # Specify model - #model = "pixtral-12b-2409" - model = data['model'] - # Define the messages for the chat - messages = [ - { - "role": "user", - "content": [ - { - "type": "text", - "text": prompt - }, - { - "type": "image_url", - "image_url": f"data:image/jpeg;base64,{image_data}" - } - ] - } - ] - - # Get the chat response - chat_response = client.chat.complete( - model=model, - messages=messages - ) - - content = chat_response.choices[0].message.content - #print(chat_response.choices[0].message.content) - # Return the content of the response - return Response({"response": content}) - except Exception as e: - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) - - -class NIMVisionLLMView(APIView): - def post(self, request, format=None): - try: - invoke_url = "https://ai.api.nvidia.com/v1/gr/meta/llama-3.2-11b-vision-instruct/chat/completions" - stream = False - api_key = os.environ["NIM_API_KEY"] - data = request.data - model = data['model'] - print(model) - image_data = (data['messages'][0]['image'][0]) - prompt = data['messages'][0]['prompt'] - headers = { - "Authorization": f"Bearer {api_key}", - "Accept": "text/event-stream" if stream else "application/json" - } - payload = { - "model": model, - "messages": [ - { - "role": "user", - "content": f'{prompt} ' - } - ], - "max_tokens": 512, - "temperature": 1.00, - "top_p": 1.00, - "stream": stream - } - response = requests.post(invoke_url, headers=headers, json=payload) - - if stream: - for line in response.iter_lines(): - if line: - #print(line.decode("utf-8")) - data = line.decode("utf-8") - #content = json.loads(data)['choices'][0]['delta'].get('content', '') - else: - #print(response.json()) - data = response.json() - content = data['choices'][0]['message']['content'] - - #print(content) - return Response({"response": content}) - - - except Exception as e: # Added general exception handling - print(f"An error occurred: {e}") - return Response({'error': 'Something went wrong'}, status=500) diff --git a/requirements.txt b/requirements.txt index b3ebc65b9c4efed61da632f3207ca88870e64210..830aa11f3e7405a7d473c61ae0dc195dddbaeb90 100644 --- a/requirements.txt +++ b/requirements.txt @@ -46,6 +46,7 @@ pytz==2024.2 PyYAML==6.0.2 requests==2.32.3 requests-oauthlib==2.0.0 +setuptools==75.6.0 six==1.16.0 sniffio==1.3.1 social-auth-app-django==5.4.2 diff --git a/spaces/settings.py b/spaces/settings.py index a8e21f7d265a5fac3feabeca9c8068a2c9f96084..f37ad306e64d82fb0efcca580dc8a0820db1497a 100644 --- a/spaces/settings.py +++ b/spaces/settings.py @@ -9,12 +9,13 @@ https://docs.djangoproject.com/en/5.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/5.1/ref/settings/ """ - +import os from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent +#BASE_DIR = Path(__file__).resolve().parent.parent # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ @@ -46,7 +47,10 @@ INSTALLED_APPS = [ 'rest_framework', 'rest_framework.authtoken', 'djoser', - 'accounts' + 'accounts', + 'games', + 'taxtech', + 'dashboard', ] MIDDLEWARE = [ @@ -148,7 +152,7 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.1/howto/static-files/ -STATIC_URL = 'static/' +#STATIC_URL = 'static/' # Default primary key field type # https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field @@ -173,3 +177,11 @@ REST_FRAMEWORK = { DJOSER = { "USER_ID_FIELD": "username" } + +STATIC_ROOT = os.path.join(BASE_DIR, 'static') + + + +# Static Files +STATIC_URL = '/static/' +STATICFILES_DIRS = [os.path.join(BASE_DIR, 'dashboard/static'),] \ No newline at end of file diff --git a/spaces/urls.py b/spaces/urls.py index 4d764f79a744b688e1c1dc4f37250ab6c3c6b02f..7a80abe38b23f2653132b7297fdf2c40bfc7e811 100644 --- a/spaces/urls.py +++ b/spaces/urls.py @@ -40,5 +40,9 @@ urlpatterns = [ path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), path('api/v1/space_walks/', include('space_walks.urls')), path('api/v1/recipes/', include('recipes.urls')), + path('api/v1/inference/', include('inference.urls')), path('api/v1/accounts/', include('accounts.urls')), + path('games/', include('games.urls')), + path('taxtech/', include('taxtech.urls')), + path('dashboard/', include('dashboard.urls')), # Include dashboard app URLs ] diff --git a/taxtech/__init__.py b/taxtech/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/taxtech/admin.py b/taxtech/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..1cecf145084ff74d5dfa3d4caf4645bf79817c6c --- /dev/null +++ b/taxtech/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from .models import TaxTechApp, Company, TaxData + +admin.site.register(TaxTechApp) + +admin.site.register(Company) + +admin.site.register(TaxData) \ No newline at end of file diff --git a/taxtech/apps.py b/taxtech/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..69bcc4116e9c2878383e4751b48cefa7d6e56147 --- /dev/null +++ b/taxtech/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TaxtechConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'taxtech' diff --git a/taxtech/engine.py b/taxtech/engine.py new file mode 100644 index 0000000000000000000000000000000000000000..6dd163641baea23a74eb6dc3dbbf7cbf344431cc --- /dev/null +++ b/taxtech/engine.py @@ -0,0 +1,213 @@ +import pandas as pd +import numpy as np +import requests +import json +from inference.mistral_inference import text_llm +from django.core.files.storage import default_storage + +def execute_prompt(prompt, local=True): + + if local: + #url = "http://10.211.137.191:11434/api/generate" + url = "http://localhost:11434/api/generate" + headers = {"Content-Type": "application/json"} + data = { + "model": "mistral", + #"model": "mistral-nemo", + "prompt": prompt, + "stream": False + } + + response = requests.post(url, headers=headers, data=json.dumps(data)) + output = "" + if response.status_code == 200: + responses = response.text.strip().split('\n') + for resp in responses: + try: + result = json.loads(resp) + print(result.get('response', '')) + output += result.get('response', '') + '\n' + except json.JSONDecodeError: + print(f"Error decoding JSON: {resp}") + + else: + print(f"Error: {response.status_code}") + return output.strip() + else: + response = text_llm(prompt) + #print(response) + return response + +from datetime import datetime + +def bundle_function(articles): + current_date = datetime.now() + bundle_articles = [] + + for article in articles: + demand = article.get('demand')*100-100 + stock = article.get('stock')*100+15 + expires_at_str = article.get('expiresAt') + + try: + expires_at = datetime.strptime(expires_at_str, '%Y-%m-%d') + days_to_expire = (expires_at - current_date).days + + #TODO change days to expire to e.g. 3 / 10 + if days_to_expire<3 or (stock > 15 and demand < 10 and days_to_expire<300): + bundle_articles.append(article) + + except (ValueError, TypeError): + print(f"Fehler beim Verarbeiten des Ablaufdatums für Artikel: {article.get('name', 'Unbekannt')} in bundle_function") + + return bundle_articles + + + + + +def propose_recipes(bundle_articles): + if bundle_articles: + bundle_article_names = ', '.join([article.get('name') for article in bundle_articles]) + + prompt = ( + f"Give me some recipes where the Bundle articles could be used. My goal is that all items in Bundle articles " + f"are used in a recipe. Seperate the response in three parts. 1. Name of the recipe, 2. Ingredients for the recipe, 3. Steps in the recipe. Answer in a JSON Format" + f"Bundle articles: {bundle_article_names}" + ) + + return prompt + + else: + return "Tell me a joke." + + + +def price_reduction(time_to_expiration, product_type, demand, stock): + """ Calculate the price reduction percentage based on normalized values + (between 0 and 1) for time to expiration, product type, demand, and stock. + + Args: + time_to_expiration (float): + Normalized time to expiration, 0 means expiring today, 1 means maximum time. + product_type (float): + Normalized product type (0 = non-perishable, 0.5 = semi-perishable, 1 = highly perishable). + demand (float): + Normalized demand (0 to 1), where 1 is high demand and 0 is no demand. + stock (float): + Normalized stock level (0 to 1), where 0 is low stock and 1 is high stock. + + Returns: + reduction_percentage (float): Percentage of price reduction. + """ + + # Maximum discouts + MAX_EXPIRATION = 0.05 + MAX_STOCK_DEMAND = 0.05 + + if time_to_expiration > 0.5: + return 0 + + # Time to expiration: Closer to expiration means higher discount (inverted) + # Maximum factor when time_to_expiration is 0 + expiration_factor = (1 - time_to_expiration) * MAX_EXPIRATION + + # Stock: Higher stock means higher discount + # Demand: Lower demand should increase discount + # Maximum factor when stock is 1 (high stock) and demand is 0 (low demand) + stock_demand_factor = (stock - demand) * MAX_STOCK_DEMAND + + # Product type: Non-perishable (0), semi-perishable (0.5), perishable (1) impact + # Factor ranges from 1.0 (non-perishable) to 1.4 (highly perishable) + product_factor = 1 + (product_type * 6.0) + + # Combine all factors to calculate total reduction + reduction_percentage = ((expiration_factor + stock_demand_factor) * product_factor) + # Cap the discount between 0% and 80% + return min(max(reduction_percentage * 100, 0), 80) + + +def compute_reduced_prices(as_json=True): + #df = pd.read_json('articles.json') + file = default_storage.open('data/articles.json', 'r') + data = json.load(file) + file.close() + df = pd.DataFrame(data) + df["product_type"] = 1 + df["time_to_expiration"] = np.random.rand(len(df.index)) + df["demand"] = np.random.rand(len(df.index)) + df["stock"] = np.random.rand(len(df.index)) + df["discount"] = df.apply(lambda row: price_reduction(row['time_to_expiration'], row['product_type'], row['demand'], row['stock']), axis=1) + df["discounted_price"] = df["price"] * (1 - df["discount"] / 100) + df = df.drop(columns=['weight', 'packagingUnit', 'available']) + + return df.to_json(orient="records") if as_json is True else df + + +def json_parser(api_json): + + explicit_prompt = """ + 1. State the name of the food item. + 2. Mention the expiration date to raise awareness about freshness. + 3. Describe the best storage practices to prolong shelf life. + 4. List creative ways to use the food item to encourage consumption before it spoils. + 5. Provide actionable tips for minimizing waste, such as recipes or preservation methods. + JSON DATA = {} + """.format(api_json) + + + implicit_prompt = """ + Analyse the data about food items, Lets think step by step + JSON DATA = {} + """.format(api_json) + + few_shot_cots = """ + JSON DATA = {} + """.format(api_json) + + categorize_articles= """ + Put the food into 3 categories. Long living food with the criteria: time to expiration greater than 3 months, middle living food with the criteria: time to expiration greater than 2 weeks and less than 3 months, short living food with the criteria: time to expiration less than 2 weeks. + JSON DATA = {} + """.format(api_json) + + return categorize_articles + +def get_json_objects(): + try: + with open('../data/articles.json', 'r') as openfile: + # Reading from json file + json_object = json.load(openfile) + + + except Exception as e: + print(f"An error occurred: {e}") + + + # debug - + first_ten_objects = json_object[:10] + return first_ten_objects + #return json_object + +def main(): + + try: + json_objs = compute_reduced_prices() + obj= json.loads(json_objs) + print(obj) + #chunk_size = 100 + #for i in range(0,len(obj), chunk_size): + #chunk = obj[i: i+chunk_size] + #level_1_prompt = json_parser(obj[:10]) + #execute_prompt(level_1_prompt) + bundle_articles = bundle_function(obj[:10]) + execute_prompt(propose_recipes(bundle_articles)) + except FileNotFoundError: + print("The file 'articles.json' was not found.") + except json.JSONDecodeError: + print("The file 'articles.json' is not a valid JSON file.") + except Exception as e: + print(f"An error occurred: {e}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/taxtech/migrations/0001_initial.py b/taxtech/migrations/0001_initial.py new file mode 100644 index 0000000000000000000000000000000000000000..2cf95a803bcee1d96d7dc2b048bd410d3a137fd9 --- /dev/null +++ b/taxtech/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.1 on 2024-11-24 11:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='TaxTechApp', + fields=[ + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('appointment_day', models.DateField()), + ('company_name', models.CharField(max_length=255)), + ('status', models.CharField(max_length=255)), + ('observations', models.TextField()), + ], + ), + ] diff --git a/taxtech/migrations/0002_auto_20241124_1235.py b/taxtech/migrations/0002_auto_20241124_1235.py new file mode 100644 index 0000000000000000000000000000000000000000..4bd69c2a14caf43f35646c63e5d5d85f33a6f461 --- /dev/null +++ b/taxtech/migrations/0002_auto_20241124_1235.py @@ -0,0 +1,19 @@ +# Generated by Django 5.1.1 on 2024-11-19 09:22 + +from django.db import migrations + +def add_default_entries(apps, schema_editor): + TaxTechApp = apps.get_model('taxtech', 'TaxTechApp') + TaxTechApp.objects.create(appointment_day='2024-11-19', company_name='User 001', status='Pending', observations='Unverified') + TaxTechApp.objects.create(appointment_day='2024-11-21', company_name='User 002', status='Confirmed', observations='Unverified') + TaxTechApp.objects.create(appointment_day='2024-12-04', company_name='User 003', status='Cancelled', observations='Unverified') + +class Migration(migrations.Migration): + + dependencies = [ + ('taxtech', '0001_initial'), + ] + + operations = [ + migrations.RunPython(add_default_entries), + ] \ No newline at end of file diff --git a/taxtech/migrations/0003_company_taxdata.py b/taxtech/migrations/0003_company_taxdata.py new file mode 100644 index 0000000000000000000000000000000000000000..fa07b1855dd9607c35bffd1e1248cf5eb2a5f0e2 --- /dev/null +++ b/taxtech/migrations/0003_company_taxdata.py @@ -0,0 +1,45 @@ +# Generated by Django 5.1.1 on 2024-11-25 09:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('taxtech', '0002_auto_20241124_1235'), + ] + + operations = [ + migrations.CreateModel( + name='Company', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('country', models.CharField(max_length=255)), + ('currency', models.CharField(max_length=10)), + ('ebt', models.IntegerField()), + ('taxes', models.IntegerField()), + ('revenues', models.IntegerField()), + ('wages', models.IntegerField()), + ('fixed_assets', models.IntegerField()), + ], + ), + migrations.CreateModel( + name='TaxData', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('country', models.CharField(max_length=255)), + ('currency', models.CharField(max_length=10)), + ('ebt', models.IntegerField()), + ('taxes', models.IntegerField()), + ('quote', models.FloatField()), + ('check_data', models.CharField(max_length=255)), + ('pot_mehrsteuer', models.IntegerField()), + ('de_minimis', models.CharField(max_length=10)), + ('five_percent_check', models.IntegerField()), + ('revenues', models.IntegerField(blank=True, null=True)), + ('salaries', models.IntegerField()), + ('net_loss', models.IntegerField()), + ], + ), + ] diff --git a/taxtech/migrations/0004_auto_20241125_1038.py b/taxtech/migrations/0004_auto_20241125_1038.py new file mode 100644 index 0000000000000000000000000000000000000000..83d296d9c5d2422d9736cf97e2b3a362edef8c91 --- /dev/null +++ b/taxtech/migrations/0004_auto_20241125_1038.py @@ -0,0 +1,333 @@ +# Generated by Django 5.1.1 on 2024-11-25 10:38 + +from django.db import migrations +from django.core.serializers.json import DjangoJSONEncoder +import json + + +def add_default_entries(apps, schema_editor): + Company = apps.get_model('taxtech', 'Company') + json_data = [ + { + "Name": "SOLAR STAR Australia Pty Ltd.", + "Country": "Australia", + "Currency": "$", + "EBT": 3110804, + "Taxes": 933287, + "Revenues": 15019053, + "Wages": 4462929, + "Fixed Assets": 490842 + }, + { + "Name": "Münchener Bau Peking Trading Co. Ltd.", + "Country": "China", + "Currency": "¥", + "EBT": 2879422, + "Taxes": 122634, + "Revenues": 18531124, + "Wages": 1287482, + "Fixed Assets": 49983 + }, + { + "Name": "SOLAR STAR Peking Co. Ltd.", + "Country": "China", + "Currency": "¥", + "EBT": 3398064, + "Taxes": 858188, + "Revenues": 48629095, + "Wages": 1791086, + "Fixed Assets": 16620 + }, + { + "Name": "SOLAR STAR Shenzhen Precision Tools Co. Ltd.", + "Country": "China", + "Currency": "¥", + "EBT": 4890481, + "Taxes": 1425081, + "Revenues": 210938122, + "Wages": 52355302, + "Fixed Assets": 23675449 + }, + { + "Name": "Helvetia STAR Nanjing Co. Ltd.", + "Country": "China", + "Currency": "¥", + "EBT": 12736577, + "Taxes": 3318591, + "Revenues": 107841917, + "Wages": 19877312, + "Fixed Assets": 9181474 + }, + { + "Name": "LASER FOCUS Solutions Ltd.", + "Country": "China", + "Currency": "¥", + "EBT": 22933642, + "Taxes": 8532294, + "Revenues": 107007592, + "Wages": 28371569, + "Fixed Assets": 7684218 + }, + { + "Name": "SOLAR STAR AG", + "Country": "Germany", + "Currency": "€", + "EBT": -6257808, + "Taxes": 25241000, + "Revenues": 78373525, + "Wages": 24276114, + "Fixed Assets": 72113495 + }, + { + "Name": "SOLAR STAR Techologien GmbH", + "Country": "Germany", + "Currency": "€", + "EBT": -13750861, + "Taxes": 1011699, + "Revenues": 29458635, + "Wages": 12183108, + "Fixed Assets": 1563488 + }, + { + "Name": "SOLAR STAR Industrial Solar Panel Germany GmbH", + "Country": "Germany", + "Currency": "€", + "EBT": 2613482, + "Taxes": -541593, + "Revenues": 49003962, + "Wages": 21250856, + "Fixed Assets": 16304595 + }, + { + "Name": "SOLAR STAR Technology GmbH", + "Country": "Germany", + "Currency": "€", + "EBT": 86892900, + "Taxes": 2203025, + "Revenues": 406030404, + "Wages": 101856077, + "Fixed Assets": 71899050 + }, + { + "Name": "SOLAR STAR Panel Industries GmbH", + "Country": "Germany", + "Currency": "€", + "EBT": 6503237, + "Taxes": 1011920, + "Revenues": 69569294, + "Wages": 24093966, + "Fixed Assets": 7266301 + }, + { + "Name": "LASER GmbH", + "Country": "Germany", + "Currency": "€", + "EBT": 14553790, + "Taxes": 1296192, + "Revenues": 92341726, + "Wages": 28630956, + "Fixed Assets": 21589109 + }, + { + "Name": "LASER Scandinavia Oy", + "Country": "Finland", + "Currency": "€", + "EBT": -425655, + "Taxes": 600, + "Revenues": 294901, + "Wages": 365941, + "Fixed Assets": 71284 + }, + { + "Name": "SOLAR STAR Industrial Solar Panel France SAS", + "Country": "France", + "Currency": "€", + "EBT": 30126, + "Taxes": 1267, + "Revenues": 6691332, + "Wages": 3044949, + "Fixed Assets": 2837295 + }, + { + "Name": "SOLAR STAR Flight Solutions UK Ltd.", + "Country": "United Kingdom", + "Currency": "£", + "EBT": -1163011, + "Taxes": -496500, + "Revenues": 17802862, + "Wages": 7638225, + "Fixed Assets": 4926736 + }, + { + "Name": "LASER Hong Kong Ltd.", + "Country": "Hong Kong", + "Currency": "HK$", + "EBT": 9105693, + "Taxes": 1354462, + "Revenues": 142579492, + "Wages": 0, + "Fixed Assets": 0 + }, + { + "Name": "SOLAR STAR Industrial Solar Panel India Private Ltd.", + "Country": "India", + "Currency": "₹", + "EBT": 21728631, + "Taxes": 4111624, + "Revenues": 127793212, + "Wages": 20120981, + "Fixed Assets": 6955992 + }, + { + "Name": "SOLAR STAR Tokio Co. Ltd.", + "Country": "Japan", + "Currency": "¥", + "EBT": -15680825, + "Taxes": -4315440, + "Revenues": 630186879, + "Wages": 106616937, + "Fixed Assets": 23725837 + }, + { + "Name": "LASER Kyoto Co. Ltd.", + "Country": "Japan", + "Currency": "¥", + "EBT": 241224668, + "Taxes": 83370716, + "Revenues": 1207927931, + "Wages": 151146587, + "Fixed Assets": 125623816 + }, + { + "Name": "SOLARTWO Consumer Ltd.", + "Country": "Canada", + "Currency": "$", + "EBT": 11767002, + "Taxes": 2666776, + "Revenues": 74227540, + "Wages": 20360137, + "Fixed Assets": 6030437 + }, + { + "Name": "SOLAR STAR Benelux B.V.", + "Country": "Netherlands", + "Currency": "€", + "EBT": 804169, + "Taxes": 163865, + "Revenues": 3600132, + "Wages": 792861, + "Fixed Assets": 429649 + }, + { + "Name": "SOLAR STAR Flight Solutions Switzerland AG", + "Country": "Switzerland", + "Currency": "CHF", + "EBT": 371618, + "Taxes": 62905, + "Revenues": 5064940, + "Wages": 964089, + "Fixed Assets": 326595 + }, + { + "Name": "Helvetia STAR AG", + "Country": "Switzerland", + "Currency": "CHF", + "EBT": 14518851, + "Taxes": 1934433, + "Revenues": 113261403, + "Wages": 44705919, + "Fixed Assets": 29984629 + }, + { + "Name": "SOLAR STAR Middle East-Asia-Pacific Pte. Ltd.", + "Country": "Singapore", + "Currency": "$", + "EBT": -585661, + "Taxes": 0, + "Revenues": 2004397, + "Wages": 415867, + "Fixed Assets": 46753 + }, + { + "Name": "LASER Singapore Pte. Ltd.", + "Country": "Singapore", + "Currency": "$", + "EBT": 376199, + "Taxes": 47124, + "Revenues": 2334164, + "Wages": 520424, + "Fixed Assets": 49001 + }, + { + "Name": "SOLAR STAR International S.L.", + "Country": "Spain", + "Currency": "€", + "EBT": -9681319, + "Taxes": 823250, + "Revenues": 1071584, + "Wages": 2543733, + "Fixed Assets": 2516270 + }, + { + "Name": "SOLAR STAR Seoul Corp. Ltd.", + "Country": "South Korea", + "Currency": "₩", + "EBT": 544369794, + "Taxes": 16250558, + "Revenues": 6899230193, + "Wages": 1110176335, + "Fixed Assets": 28179496 + }, + { + "Name": "LASER Seoul Co. Ltd.", + "Country": "South Korea", + "Currency": "₩", + "EBT": 324790107, + "Taxes": 43581880, + "Revenues": 3468920376, + "Wages": 1114736450, + "Fixed Assets": 338538646 + }, + { + "Name": "LASER Taipeh Ltd.", + "Country": "Taiwan", + "Currency": "$", + "EBT": 27964294, + "Taxes": 5647274, + "Revenues": 173775171, + "Wages": 21404306, + "Fixed Assets": 13571150 + }, + { + "Name": "SOLAR STAR North America Inc.", + "Country": "USA", + "Currency": "$", + "EBT": -1528575, + "Taxes": 1301266, + "Revenues": 767515, + "Wages": 0, + "Fixed Assets": 0 + } + ] + + for entry in json_data: + Company.objects.create( + name=entry['Name'], + country=entry['Country'], + currency=entry['Currency'], + ebt=entry['EBT'], + taxes=entry['Taxes'], + revenues=entry['Revenues'], + wages=entry['Wages'], + fixed_assets=entry['Fixed Assets'], + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('taxtech', '0003_company_taxdata'), + ] + operations = [ + migrations.RunPython(add_default_entries), + ] \ No newline at end of file diff --git a/taxtech/migrations/0005_auto_20241125_1043.py b/taxtech/migrations/0005_auto_20241125_1043.py new file mode 100644 index 0000000000000000000000000000000000000000..fb98ca5905060163ed9f736afcee4b17fe093105 --- /dev/null +++ b/taxtech/migrations/0005_auto_20241125_1043.py @@ -0,0 +1,276 @@ +# Generated by Django 5.1.1 on 2024-11-25 10:43 + +from django.db import migrations +from django.core.serializers.json import DjangoJSONEncoder +import json + + +def add_default_entries(apps, schema_editor): + TaxData = apps.get_model('taxtech', 'TaxData') + data = [ + { + "Country": "Land Australien", + "Currency": "€", + "EBT": 2050144, + "Taxes": 615074, + "Quote": 30.00, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 9898156, + "De Minimis?": "N/A", + "5% Check": 24397, + "Revenues": None, + "Salaries": 348962, + "Net Loss": -40501 + }, + { + "Country": "Land China", + "Currency": "€", + "EBT": 6615474, + "Taxes": 2013643, + "Quote": 30.44, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 69624464, + "De Minimis?": "N/A", + "5% Check": 430459, + "Revenues": None, + "Salaries": -17508, + "Net Loss": -117654 + }, + { + "Country": "Land Deutschland", + "Currency": "€", + "EBT": 90554740, + "Taxes": 30222242, + "Quote": 33.37, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 724777547, + "De Minimis?": "N/A", + "5% Check": 14877411, + "Revenues": None, + "Salaries": 22201920, + "Net Loss": -235523 + }, + { + "Country": "Land Finnland", + "Currency": "€", + "EBT": -425655, + "Taxes": 600, + "Quote": -0.14, + "Check_Data": "Nein, Verlust im Land", + "Pot. Mehrsteuer": 294901, + "De Minimis?": "N/A", + "5% Check": 5560, + "Revenues": None, + "Salaries": 600, + "Net Loss": 0 + }, + { + "Country": "Land Frankreich", + "Currency": "€", + "EBT": 30126, + "Taxes": 1267, + "Quote": 4.20, + "Check_Data": "Ja, Gewinn und Quote unter 15%", + "Pot. Mehrsteuer": 4519, + "De Minimis?": "De Minimus' Test greift", + "5% Check": 6691332, + "Revenues": None, + "Salaries": 298405, + "Net Loss": 0 + }, + { + "Country": "Land Großbritannien", + "Currency": "€", + "EBT": -1364065, + "Taxes": -582332, + "Quote": 42.69, + "Check_Data": "Nein, Verlust im Land", + "Pot. Mehrsteuer": 20880504, + "De Minimis?": "N/A", + "5% Check": 433276, + "Revenues": None, + "Salaries": 0, + "Net Loss": 0 + }, + { + "Country": "Land Hongkong", + "Currency": "€", + "EBT": 1103555, + "Taxes": 164153, + "Quote": 14.87, + "Check_Data": "Ja, Gewinn und Quote unter 15%", + "Pot. Mehrsteuer": 165533, + "De Minimis?": "Kein 'De Minimus' Fall; EBT zu hoch; Umsatz zu hoch", + "5% Check": 17279773, + "Revenues": 1103555, + "Salaries": 0, + "Net Loss": 1381 + }, + { + "Country": "Land Indien", + "Currency": "€", + "EBT": 262694, + "Taxes": 49709, + "Quote": 18.92, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 1544992, + "De Minimis?": "N/A", + "5% Check": 6154, + "Revenues": None, + "Salaries": -28863, + "Net Loss": 0 + }, + { + "Country": "Land Japan", + "Currency": "€", + "EBT": 1634316, + "Taxes": 572843, + "Quote": 35.05, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 13319184, + "De Minimis?": "N/A", + "5% Check": 82819, + "Revenues": None, + "Salaries": 38108, + "Net Loss": 0 + }, + { + "Country": "Land Kanada", + "Currency": "€", + "EBT": 8586955, + "Taxes": 1946076, + "Quote": 22.66, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 54167451, + "De Minimis?": "N/A", + "5% Check": 325744, + "Revenues": None, + "Salaries": 169119, + "Net Loss": -186086 + }, + { + "Country": "Land Niederlande", + "Currency": "€", + "EBT": 804169, + "Taxes": 163865, + "Quote": 20.38, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 3600132, + "De Minimis?": "N/A", + "5% Check": 33513, + "Revenues": None, + "Salaries": 5548, + "Net Loss": 0 + }, + { + "Country": "Land Schweiz", + "Currency": "€", + "EBT": 14813848, + "Taxes": 1987060, + "Quote": 13.41, + "Check_Data": "Ja, Gewinn und Quote unter 15%", + "Pot. Mehrsteuer": 2222077, + "De Minimis?": "Kein 'De Minimus' Fall; EBT zu hoch; Umsatz zu hoch", + "5% Check": 117717474, + "Revenues": 7960207, + "Salaries": 4452630, + "Net Loss": 0 + }, + { + "Country": "Land Singapur", + "Currency": "€", + "EBT": -144261, + "Taxes": 32455, + "Quote": -22.50, + "Check_Data": "Nein, Verlust im Land", + "Pot. Mehrsteuer": 2988059, + "De Minimis?": "N/A", + "5% Check": 5223, + "Revenues": None, + "Salaries": 0, + "Net Loss": 0 + }, + { + "Country": "Land Spanien", + "Currency": "€", + "EBT": -9681319, + "Taxes": 823250, + "Quote": -8.50, + "Check_Data": "Nein, Verlust im Land", + "Pot. Mehrsteuer": 1071584, + "De Minimis?": "N/A", + "5% Check": 196269, + "Revenues": None, + "Salaries": 812250, + "Net Loss": 0 + }, + { + "Country": "Land Südkorea", + "Currency": "€", + "EBT": 639996, + "Taxes": 44057, + "Quote": 6.88, + "Check_Data": "Ja, Gewinn und Quote unter 15%", + "Pot. Mehrsteuer": 95999, + "De Minimis?": "De Minimus' Test greift", + "5% Check": 7634468, + "Revenues": None, + "Salaries": 160552, + "Net Loss": 0 + }, + { + "Country": "Land Taiwan", + "Currency": "€", + "EBT": 892780, + "Taxes": 180293, + "Quote": 20.19, + "Check_Data": "Nein, Gewinn und Quote>= 15%", + "Pot. Mehrsteuer": 5547897, + "De Minimis?": "N/A", + "5% Check": 32348, + "Revenues": None, + "Salaries": -20675, + "Net Loss": 1277 + }, + { + "Country": "Land USA", + "Currency": "€", + "EBT": -1450430, + "Taxes": 1234741, + "Quote": -85.13, + "Check_Data": "Nein, Verlust im Land", + "Pot. Mehrsteuer": 728277, + "De Minimis?": "N/A", + "5% Check": 0, + "Revenues": None, + "Salaries": 3205307, + "Net Loss": -41751 + } + ] + + for item in data: + TaxData.objects.create( + country=item['Country'], + currency=item['Currency'], + ebt=item['EBT'], + taxes=item['Taxes'], + quote=item['Quote'], + check_data=item['Check_Data'], + pot_mehrsteuer=item['Pot. Mehrsteuer'], + de_minimis=item['De Minimis?'], + five_percent_check=item['5% Check'], + revenues=item['Revenues'], + salaries=item['Salaries'], + net_loss=item['Net Loss'] + ) + + +class Migration(migrations.Migration): + + dependencies = [ + ('taxtech', '0004_auto_20241125_1038'), + ] + + operations = [ + migrations.RunPython(add_default_entries), + ] \ No newline at end of file diff --git a/taxtech/migrations/__init__.py b/taxtech/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/taxtech/models.py b/taxtech/models.py new file mode 100644 index 0000000000000000000000000000000000000000..858cc8e9aebb13090f0cfa59d1bb02295ba110ef --- /dev/null +++ b/taxtech/models.py @@ -0,0 +1,37 @@ +from django.db import models + +class TaxTechApp(models.Model): + id = models.BigAutoField(primary_key=True) + appointment_day = models.DateField() + company_name = models.CharField(max_length=255) + status = models.CharField(max_length=255) + observations = models.TextField() + +class TaxData(models.Model): + country = models.CharField(max_length=255) + currency = models.CharField(max_length=10) + ebt = models.IntegerField() + taxes = models.IntegerField() + quote = models.FloatField() + check_data = models.CharField(max_length=255) + pot_mehrsteuer = models.IntegerField() + de_minimis = models.CharField(max_length=10) + five_percent_check = models.IntegerField() + revenues = models.IntegerField(null=True, blank=True) + salaries = models.IntegerField() + net_loss = models.IntegerField() + +# backend/taxtech/models.py + +class Company(models.Model): + name = models.CharField(max_length=255) + country = models.CharField(max_length=255) + currency = models.CharField(max_length=10) + ebt = models.IntegerField() + taxes = models.IntegerField() + revenues = models.IntegerField() + wages = models.IntegerField() + fixed_assets = models.IntegerField() + + def __str__(self): + return self.name \ No newline at end of file diff --git a/taxtech/serializers.py b/taxtech/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..8ba9644ab672f830156435f58156dcd06768d145 --- /dev/null +++ b/taxtech/serializers.py @@ -0,0 +1,19 @@ +from rest_framework import serializers +from .models import TaxTechApp, TaxData, Company + +class TaxTechAppSerializer(serializers.ModelSerializer): + class Meta: + model = TaxTechApp + fields = '__all__' + + +class TaxDataSerializer(serializers.ModelSerializer): + class Meta: + model = TaxData + fields = '__all__' + + +class CompanySerializer(serializers.ModelSerializer): + class Meta: + model = Company + fields = '__all__' \ No newline at end of file diff --git a/taxtech/tests.py b/taxtech/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/taxtech/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/taxtech/urls.py b/taxtech/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..45d6e7574876b418336749ba13d71a9c02d5f39a --- /dev/null +++ b/taxtech/urls.py @@ -0,0 +1,16 @@ +from django.urls import path, include +from rest_framework.routers import DefaultRouter +from .views import TaxTechAppViewSet, TaxLLMView, TaxDataViewSet, CompanyViewSet + +router = DefaultRouter() +router.register(r'taxtechapp', TaxTechAppViewSet) +router.register(r'taxdata', TaxDataViewSet) +router.register(r'company', CompanyViewSet) + + + +urlpatterns = [ + # ... other URL patterns + path('taxdata/', include(router.urls)), + path('tax_llm_url/', TaxLLMView.as_view(), name='tax_llm_url'), +] \ No newline at end of file diff --git a/taxtech/views.py b/taxtech/views.py new file mode 100644 index 0000000000000000000000000000000000000000..0920e0066a67577daec42683530bca696eb1a70f --- /dev/null +++ b/taxtech/views.py @@ -0,0 +1,136 @@ +from django.shortcuts import render +from django.core.files.storage import FileSystemStorage +import django_filters +from rest_framework import viewsets +from rest_framework.decorators import action +from rest_framework.response import Response +from rest_framework.pagination import LimitOffsetPagination +from django.utils import timezone +from datetime import datetime, timedelta +import requests + +from .models import TaxTechApp, TaxData, Company +from .serializers import TaxTechAppSerializer, CompanySerializer, TaxDataSerializer + +from django.http import JsonResponse +from rest_framework.response import Response +from rest_framework.views import APIView +from mistralai import Mistral +import os +import requests +from openai import OpenAI +from ollama import Client +from django.http import FileResponse +import io +from rest_framework.pagination import PageNumberPagination + + + +class TaxTechAppPagination(PageNumberPagination): + page_size = 10 + page_size_query_param = 'page_size' + max_page_size = 100 + +class TaxTechAppViewSet(viewsets.ModelViewSet): + queryset = TaxTechApp.objects.all().order_by('id') + serializer_class = TaxTechAppSerializer + pagination_class = TaxTechAppPagination + + + +class TaxDataPagination(PageNumberPagination): + page_size = 10 + page_size_query_param = 'page_size' + max_page_size = 100 + +class TaxDataViewSet(viewsets.ModelViewSet): + queryset = TaxData.objects.all().order_by('id') + serializer_class = TaxDataSerializer + pagination_class = TaxDataPagination + + +class CompanyPagination(PageNumberPagination): + page_size = 10 + page_size_query_param = 'page_size' + max_page_size = 100 + +class CompanyViewSet(viewsets.ModelViewSet): + queryset = Company.objects.all().order_by('id') + serializer_class = CompanySerializer + pagination_class = CompanyPagination + + +from rest_framework.decorators import api_view +from rest_framework.response import Response +from .engine import execute_prompt, bundle_function, propose_recipes, compute_reduced_prices +import json + +@api_view(['GET']) +def recipe_generate_route(request): + isLocal = False + try: + json_objs = compute_reduced_prices() + obj= json.loads(json_objs) + bundle_articles = bundle_function(obj[:10]) + + result = execute_prompt(propose_recipes(bundle_articles), False) + except (FileNotFoundError, json.JSONDecodeError) as e: + return Response({'error': str(e)}, status=500) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500) + return Response(result) + + +class TaxLLMView(APIView): + def post(self, request, format=None): + try: + data = request.data + + #isOnline = data['isOnline'] + isOnline = True + + prompt = data['messages'][0]['prompt'] + # Specify model + #model = "pixtral-12b-2409" + model = data['model'] + # Define the messages for the chat + messages = [ + { + "role": "system", + "content": "Please provide a concise response, limiting your answer to three lines or less." + }, + { + "role": "user", + "content": [ + { + "type": "text", + "text": prompt + } + ] + } + ] + + if(isOnline): + api_key = os.environ["MISTRAL_API_KEY"] + + # Initialize the Mistral client + client = Mistral(api_key=api_key) + + + # Get the chat response + chat_response = client.chat.complete( + model=model, + messages=messages + ) + + content = chat_response.choices[0].message.content + else: + content = "helloWorld" + + #print(chat_response.choices[0].message.content) + # Return the content of the response + return Response({"response": content}) + except Exception as e: + print(f"An error occurred: {e}") + return Response({'error': 'Something went wrong'}, status=500)