Add management command to import csv and update template
This commit is contained in:
parent
38b56deeec
commit
9a4a70dfb6
5 changed files with 150 additions and 58 deletions
89
main/management/commands/import_fuelpurchases.py
Normal file
89
main/management/commands/import_fuelpurchases.py
Normal file
|
@ -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"))
|
60
main/management/commands/import_monthly_trips.py
Normal file
60
main/management/commands/import_monthly_trips.py
Normal file
|
@ -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!"))
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -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'),
|
||||
),
|
||||
]
|
|
@ -37,7 +37,7 @@
|
|||
<li><strong>Average Litre Price:</strong> {{ summary.avg_price|floatformat:3|default:"0.000" }} €</li>
|
||||
<li><strong>Min Litre Price:</strong> {{ summary.min_price|floatformat:3|default:"0.000" }} €</li>
|
||||
<li><strong>Max Litre Price:</strong> {{ summary.max_price|floatformat:3|default:"0.000" }} €</li>
|
||||
<li><strong>Trips:</strong> {{ month_kilometers }} km</li>
|
||||
<li><strong>Month's trips:</strong> {{ month_kilometers }} km</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue