Initial deploy setup
deploy / deploy (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-21 14:00:00 +02:00
commit b8091e59bd
285 changed files with 27854 additions and 0 deletions
View File
@@ -0,0 +1,71 @@
from __future__ import annotations
import os
from pathlib import Path
from django.contrib.auth import get_user_model
from django.core.management import call_command
from django.core.management.base import BaseCommand, CommandError
from apps.profiles.models import SearchProfile
from apps.profiles.services import save_profile_revision
class Command(BaseCommand):
help = "Maakt het eerste account, een standaardzoekprofiel en optionele demodata."
def add_arguments(self, parser):
parser.add_argument("--with-demo", action="store_true")
parser.add_argument(
"--username", default=os.getenv("VACATURERADAR_ADMIN_USERNAME", "admin")
)
parser.add_argument("--email", default=os.getenv("VACATURERADAR_ADMIN_EMAIL", ""))
parser.add_argument("--password", default=os.getenv("VACATURERADAR_ADMIN_PASSWORD", ""))
def handle(self, *args, **options):
User = get_user_model()
username = options["username"]
password = options["password"]
user, created = User.objects.get_or_create(
username=username,
defaults={"email": options["email"], "is_staff": True, "is_superuser": True},
)
if created:
if not password or password.startswith("CHANGE_ME"):
raise CommandError("Stel VACATURERADAR_ADMIN_PASSWORD in of geef --password mee.")
user.set_password(password)
user.save()
self.stdout.write(self.style.SUCCESS(f"Beheerder {username} aangemaakt."))
else:
self.stdout.write(f"Beheerder {username} bestaat al.")
profile, profile_created = SearchProfile.objects.get_or_create(
user=user,
name="Primair IT-profiel",
defaults={
"is_active": True,
"desired_titles": [
"systeembeheerder",
"system engineer",
"infrastructure engineer",
"workplace engineer",
],
"excluded_titles": ["sales", "recruiter"],
"desired_skills": ["Microsoft 365", "Windows Server", "VMware", "netwerk"],
"preferred_workplace": ["hybrid", "on_site"],
},
)
if profile_created:
save_profile_revision(profile, reason="bootstrap")
self.stdout.write(self.style.SUCCESS("Standaardzoekprofiel aangemaakt."))
if options["with_demo"]:
fixture = Path("fixtures/pages/sample_jsonld_job.html")
if fixture.exists():
call_command(
"import_job_fixture",
str(fixture),
url="https://jobs.example.org/vacatures/infrastructure-engineer",
source_name="Voorbeeldwerkgever",
)
self.stdout.write(self.style.SUCCESS("Demovacature geïmporteerd."))
@@ -0,0 +1,78 @@
from __future__ import annotations
from pathlib import Path
from urllib.parse import urlparse
from django.db.models import Q
from django.core.management.base import BaseCommand, CommandError
from apps.jobs.models import JobPosting
from apps.jobs.services.scoring import rescore_jobs_with_profiles
from apps.jobs.services.geocoding import import_csv_geodata, validate_csv_geodata
class Command(BaseCommand):
help = "Importeer een lokaal Belgische postcodetabelbestand (CSV) als geocodebron."
def add_arguments(self, parser):
parser.add_argument("path", help="Pad naar CSV met postcode/gemeente-rijen.")
parser.add_argument("--source-name", default="local", help="Bronnaam voor deze dataset.")
parser.add_argument(
"--dataset-version",
default="manual",
help="Versie/identificatie van deze bron.",
)
parser.add_argument(
"--license-name", default="", help="Optionele licentienaam voor bronmetadata."
)
parser.add_argument(
"--license-url", default="", help="Optionele licentielink voor bronmetadata."
)
parser.add_argument(
"--validate-only", action="store_true", help="Alleen valideren, niet importeren."
)
parser.add_argument(
"--replace",
action="store_true",
help="Bestaande lookuprecords voor bron+versie eerst wissen.",
)
@staticmethod
def _validate_metadata(license_name: str, license_url: str) -> None:
if bool(license_name) != bool(license_url):
raise CommandError(
"Vul --license-name en --license-url altijd samen in of laat beide leeg."
)
if license_url:
parsed = urlparse(license_url)
if not parsed.scheme or not parsed.netloc:
raise CommandError("license-url moet een geldige absolute URL zijn.")
def handle(self, *args, **options):
path = Path(options["path"])
self._validate_metadata(options["license_name"], options["license_url"])
count, _ = validate_csv_geodata(path)
if options["validate_only"]:
self.stdout.write(self.style.SUCCESS(f"Validatie geslaagd ({count} rijen)."))
return
imported, postalcodes, municipalities = import_csv_geodata(
path,
source_name=options["source_name"],
source_version=options["dataset_version"],
source_license_name=options["license_name"],
source_license_url=options["license_url"],
replace=options["replace"],
)
self.stdout.write(
self.style.SUCCESS(f"Geocodebron geimporteerd ({imported} lookuprijen) uit {path}.")
)
jobs_to_rescore = JobPosting.objects.filter(status=JobPosting.Status.ACTIVE).filter(
Q(postal_code__in=postalcodes) | Q(municipality__in=municipalities)
)
if jobs_to_rescore.exists():
scored = rescore_jobs_with_profiles(jobs_to_rescore)
self.stdout.write(
self.style.NOTICE(f"{scored} scoreregels herberekend voor aangepaste geodata.")
)