diff --git a/main/management/commands/import_fuelpurchases.py b/main/management/commands/import_fuelpurchases.py new file mode 100644 index 0000000..6230625 --- /dev/null +++ b/main/management/commands/import_fuelpurchases.py @@ -0,0 +1,89 @@ +import csv +import datetime +import re +from decimal import Decimal + +from django.core.management.base import BaseCommand + +from main.models import FuelPurchase + + +class Command(BaseCommand): + help = "Import fuel purchases from CSV file" + + # Valintakenttien sanakirjat nimistä arvoiksi + GAS_STATION_MAP = { + 'Neste': 1, + 'Teboil': 2, + 'ABC': 3, + 'Shell': 4, + 'St1': 5, + 'SEO': 6, + 'ysi5': 7, + '-': 0, + } + + OCTANE_MAP = { + '95': 95, + '98': 98, + } + + CAR_MAP = { + '_': 0, + 'Renault': 1, + 'Nissan': 2, + 'Smart': 3, + } + + def add_arguments(self, parser): + parser.add_argument('csvfile', type=str, help='Path to the CSV file') + + def parse_decimal(self, value_str): + # Poista kaikki ei-numerot/pilkku/piste ja korvaa pilkut pisteeksi + # esim. "10,00 €" -> "10.00" + value_str = value_str.strip() + # poista valuuttamerkit ja välilyönnit + value_str = re.sub(r'[^\d,.-]', '', value_str) + value_str = value_str.replace(',', '.') + return Decimal(value_str) + + def parse_date(self, date_str): + # Muoto: 08.02.2015 + return datetime.datetime.strptime(date_str, "%d.%m.%Y").date() + + def handle(self, *args, **options): + file_path = options['csvfile'] + with open(file_path, newline='', encoding='utf-8') as csvfile: + reader = csv.DictReader(csvfile, delimiter=';') + count = 0 + for row in reader: + try: + purchase_date = self.parse_date(row['Päivämäärä']) + total_cost = self.parse_decimal(row['Hinta €']) + price_per_litre = self.parse_decimal(row['Litrahinta €']) + amount_litres = self.parse_decimal(row['Litraa']) + + gas_station_name = row['Asema'].strip() + gas_station = self.GAS_STATION_MAP.get(gas_station_name, 0) + + octane_name = row['Polttoaine'].strip() + octane = self.OCTANE_MAP.get(octane_name, 95) + + car_name = row['Auto'].strip() + car = self.CAR_MAP.get(car_name, 0) + + obj, created = FuelPurchase.objects.get_or_create( + purchase_date=purchase_date, + gas_station=gas_station, + octane=octane, + car=car, + total_cost=total_cost, + price_per_litre=price_per_litre, + amount_litres=amount_litres + ) + if created: + count += 1 + except Exception as e: + self.stderr.write(f"Error processing row {row}: {e}") + + self.stdout.write(self.style.SUCCESS(f"Imported {count} fuel purchase records")) diff --git a/main/management/commands/import_monthly_trips.py b/main/management/commands/import_monthly_trips.py new file mode 100644 index 0000000..f392df9 --- /dev/null +++ b/main/management/commands/import_monthly_trips.py @@ -0,0 +1,60 @@ +import csv + +from django.core.management.base import BaseCommand + +from main.models import MonthlyTrip + + +class Command(BaseCommand): + help = "Import fuel purchases from a CSV file" + + def add_arguments(self, parser): + parser.add_argument('csv_file', type=str, help='Path to the CSV file') + + def handle(self, *args, **kwargs): + csv_file = kwargs['csv_file'] + + MONTH_MAP = { + 'Tammikuu': 1, + 'Helmikuu': 2, + 'Maaliskuu': 3, + 'Huhtikuu': 4, + 'Toukokuu': 5, + 'Kesäkuu': 6, + 'Heinäkuu': 7, + 'Elokuu': 8, + 'Syyskuu': 9, + 'Lokakuu': 10, + 'Marraskuu': 11, + 'Joulukuu': 12, + } + + with open(csv_file, newline='', encoding='utf-8') as f: + reader = csv.reader(f, delimiter=';') + headers = next(reader) + + for line_number, row in enumerate(reader, start=2): + if len(row) < 3: + self.stdout.write(self.style.WARNING(f"Skipped broken row {line_number}: {row}")) + continue + + try: + year_str, month_name, value_str = row + + year = int(year_str.strip()) + month = MONTH_MAP.get(month_name.strip()) + value = int(value_str.strip()) + + MonthlyTrip.objects.update_or_create( + year=year, + month=month, + kilometers=value, + ) + + self.stdout.write(self.style.SUCCESS(f"Imported: {year} {month} {value}")) + + except Exception as e: + self.stdout.write(self.style.ERROR(f"Error on row {line_number}: {row}")) + self.stdout.write(self.style.ERROR(str(e))) + + self.stdout.write(self.style.SUCCESS("All imported successfully!")) diff --git a/main/migrations/0002_remove_fuelpurchase_unique_fuel_purchase_and_more.py b/main/migrations/0002_remove_fuelpurchase_unique_fuel_purchase_and_more.py deleted file mode 100644 index 9968611..0000000 --- a/main/migrations/0002_remove_fuelpurchase_unique_fuel_purchase_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.2.5 on 2025-08-09 18:42 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('main', '0001_initial'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='fuelpurchase', - name='unique_fuel_purchase', - ), - migrations.AddField( - model_name='fuelpurchase', - name='gas_station', - field=models.IntegerField(choices=[(0, '-'), (1, 'Neste'), (2, 'Teboil'), (3, 'ABC'), (4, 'Shell'), (5, 'St1'), (6, 'SEO'), (7, 'ysi5')], default=1, verbose_name='Gas Station'), - ), - migrations.AddField( - model_name='fuelpurchase', - name='octane', - field=models.IntegerField(choices=[(95, '95'), (98, '98')], default=95, verbose_name='Octane'), - ), - migrations.AddConstraint( - model_name='fuelpurchase', - constraint=models.UniqueConstraint(fields=('purchase_date', 'total_cost', 'price_per_litre', 'amount_litres', 'octane', 'gas_station'), name='unique_fuel_purchase'), - ), - ] diff --git a/main/migrations/0003_remove_fuelpurchase_unique_fuel_purchase_and_more.py b/main/migrations/0003_remove_fuelpurchase_unique_fuel_purchase_and_more.py deleted file mode 100644 index 1050a86..0000000 --- a/main/migrations/0003_remove_fuelpurchase_unique_fuel_purchase_and_more.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 5.2.5 on 2025-08-09 19:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('main', '0002_remove_fuelpurchase_unique_fuel_purchase_and_more'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='fuelpurchase', - name='unique_fuel_purchase', - ), - migrations.AddField( - model_name='fuelpurchase', - name='car', - field=models.IntegerField(choices=[(0, '_'), (1, 'Renault'), (2, 'Nissan'), (3, 'Smart')], default=3, verbose_name='Car'), - ), - migrations.AddConstraint( - model_name='fuelpurchase', - constraint=models.UniqueConstraint(fields=('purchase_date', 'total_cost', 'price_per_litre', 'amount_litres', 'octane', 'gas_station', 'car'), name='unique_fuel_purchase'), - ), - ] diff --git a/main/templates/main/fuelpurchase_list.html b/main/templates/main/fuelpurchase_list.html index ca8f13b..6eb1dfc 100644 --- a/main/templates/main/fuelpurchase_list.html +++ b/main/templates/main/fuelpurchase_list.html @@ -37,7 +37,7 @@