verwaltungstracker/froide_govplan/plan_importer.py
2022-03-15 14:36:32 +01:00

115 lines
3.7 KiB
Python

import datetime
import re
from django.template.defaultfilters import slugify
from froide.publicbody.models import Category, PublicBody
from .models import GovernmentPlan, GovernmentPlanSection
class PlanImporter(object):
def __init__(self, government, col_mapping=None):
if col_mapping is None:
col_mapping = {}
self.col_mapping = col_mapping
self.government = government
self.post_save_list = []
def import_rows(self, reader):
for row in reader:
self.import_row(row)
def import_row(self, row):
print("importing", row)
title = row[self.col_mapping["title"]]
if not title:
return
plan = GovernmentPlan.objects.filter(
government=self.government, title=title
).first()
if not plan:
plan = GovernmentPlan(government=self.government)
self.post_save_list = []
for col, row_col in self.col_mapping.items():
method_name = "handle_{}".format(col)
if hasattr(self, method_name):
getattr(self, method_name)(plan, row[row_col])
else:
setattr(plan, col, row[row_col])
plan.save()
for func in self.post_save_list:
func(plan)
def handle_title(self, plan, title):
plan.title = title
plan.slug = slugify(title)
def handle_categories(self, plan, category_name):
categories = [
x.strip() for x in re.split(r", | & | und ", category_name) if x.strip()
]
self.make_section(category_name, "-".join(categories), categories)
if categories:
self.post_save_list.append(lambda p: p.categories.set(*categories))
def make_section(self, section_name, section_slug, categories):
slug = slugify(section_slug)
section, _created = GovernmentPlanSection.objects.get_or_create(
slug=slug,
defaults={
"government": self.government,
"title": section_name,
},
)
section.categories.set([self.get_category(c) for c in categories])
def get_category(self, cat_name):
return Category.objects.get(name=cat_name)
def handle_reference(self, plan, reference):
plan.reference = ", ".join(re.split(r"\s*[,/]\s*", reference))
def handle_responsible_publicbody(self, plan, pb):
if not pb.strip():
return
pb = PublicBody.objects.get(
jurisdiction=self.government.jurisdiction,
other_names__iregex=r"(\W|^){}(\W|$)".format(pb),
)
plan.responsible_publicbody = pb
def handle_due_date(self, plan, date_descr):
if not date_descr.strip():
return
def parse_date(date_descr):
match = re.search(r"(\d{4})", date_descr)
if not match:
return
year = int(match.group(1))
if "Mitte" in date_descr:
return datetime.date(year, 7, 1)
if "Ende" in date_descr:
return datetime.date(year, 12, 1)
if "Anfang" in date_descr:
return datetime.date(year, 3, 1)
if "Innerhalb" in date_descr:
return datetime.date(year, 12, 31)
if "Juni" in date_descr:
return datetime.date(year, 6, 1)
return datetime.date(year, 1, 1)
plan.due_date = parse_date(date_descr)
def handle_status(self, plan, status):
status = status.strip()
if not status or status == "noch nicht umgesetzt":
status = "not_started"
if status == "umgesetzt":
status = "implemented"
if status == "begonnen":
status = "started"
plan.status = status