239 lines
15 KiB
Python
239 lines
15 KiB
Python
# Generated by Django 5.2.16 on 2026-07-20 23:57
|
|
|
|
import django.db.models.deletion
|
|
import django.utils.timezone
|
|
import uuid
|
|
from django.conf import settings
|
|
from django.db import migrations, models
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
initial = True
|
|
|
|
dependencies = [
|
|
('profiles', '0001_initial'),
|
|
('sources', '0001_initial'),
|
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name='Employer',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('name', models.CharField(max_length=300)),
|
|
('normalized_name', models.CharField(db_index=True, max_length=300)),
|
|
('domain', models.CharField(blank=True, db_index=True, max_length=255)),
|
|
('is_direct_employer', models.BooleanField(default=True)),
|
|
('is_recruiter', models.BooleanField(default=False)),
|
|
('employer_type', models.CharField(blank=True, max_length=80)),
|
|
('confidence', models.DecimalField(decimal_places=3, default=0.5, max_digits=4)),
|
|
('aliases', models.JSONField(blank=True, default=list)),
|
|
('metadata', models.JSONField(blank=True, default=dict)),
|
|
],
|
|
options={
|
|
'ordering': ['name'],
|
|
'constraints': [models.UniqueConstraint(fields=('normalized_name', 'domain'), name='unique_employer_name_domain')],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='JobPosting',
|
|
fields=[
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
('original_title', models.CharField(max_length=500)),
|
|
('normalized_title', models.CharField(db_index=True, max_length=500)),
|
|
('job_family', models.CharField(blank=True, db_index=True, max_length=160)),
|
|
('seniority', models.CharField(blank=True, max_length=80)),
|
|
('language', models.CharField(blank=True, max_length=16)),
|
|
('canonical_url', models.URLField(blank=True, db_index=True, max_length=2000)),
|
|
('canonical_key', models.CharField(max_length=64, unique=True)),
|
|
('content_hash', models.CharField(db_index=True, max_length=64)),
|
|
('description_html_sanitized', models.TextField(blank=True)),
|
|
('description_text', models.TextField(blank=True)),
|
|
('requirements', models.JSONField(blank=True, default=list)),
|
|
('benefits', models.JSONField(blank=True, default=list)),
|
|
('raw_location', models.CharField(blank=True, max_length=500)),
|
|
('country', models.CharField(blank=True, max_length=120)),
|
|
('region', models.CharField(blank=True, db_index=True, max_length=160)),
|
|
('municipality', models.CharField(blank=True, db_index=True, max_length=160)),
|
|
('postal_code', models.CharField(blank=True, max_length=24)),
|
|
('latitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
|
('longitude', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True)),
|
|
('workplace_type', models.CharField(choices=[('on_site', 'Op locatie'), ('hybrid', 'Hybride'), ('remote', 'Remote'), ('unknown', 'Onbekend')], default='unknown', max_length=20)),
|
|
('employment_types', models.JSONField(blank=True, default=list)),
|
|
('hours_text', models.CharField(blank=True, max_length=200)),
|
|
('compensation', models.JSONField(blank=True, default=dict)),
|
|
('skills_required', models.JSONField(blank=True, default=list)),
|
|
('skills_preferred', models.JSONField(blank=True, default=list)),
|
|
('analysis_features', models.JSONField(blank=True, default=dict)),
|
|
('date_posted', models.DateTimeField(blank=True, null=True)),
|
|
('valid_through', models.DateTimeField(blank=True, db_index=True, null=True)),
|
|
('first_seen', models.DateTimeField(default=django.utils.timezone.now)),
|
|
('last_seen', models.DateTimeField(db_index=True, default=django.utils.timezone.now)),
|
|
('last_changed', models.DateTimeField(default=django.utils.timezone.now)),
|
|
('status', models.CharField(choices=[('new', 'Nieuw'), ('active', 'Actief'), ('uncertain', 'Onzeker'), ('expired', 'Verlopen'), ('removed', 'Verwijderd'), ('duplicate', 'Duplicaat'), ('quarantined', 'Quarantaine')], db_index=True, default='new', max_length=20)),
|
|
('direct_employer', models.BooleanField(default=True)),
|
|
('recruiter', models.BooleanField(default=False)),
|
|
('extraction_confidence', models.DecimalField(decimal_places=3, default=0.5, max_digits=4)),
|
|
('duplicate_of', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='duplicates', to='jobs.jobposting')),
|
|
('employer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='jobs', to='jobs.employer')),
|
|
],
|
|
options={
|
|
'ordering': ['-first_seen'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='Feedback',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('action', models.CharField(choices=[('interesting', 'Interessant'), ('save', 'Bewaren'), ('hide', 'Verbergen'), ('applied', 'Gesolliciteerd'), ('undo', 'Ongedaan maken')], max_length=20)),
|
|
('reason', models.CharField(blank=True, max_length=200)),
|
|
('metadata', models.JSONField(blank=True, default=dict)),
|
|
('profile', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='profiles.searchprofile')),
|
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
|
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='feedback', to='jobs.jobposting')),
|
|
],
|
|
options={
|
|
'ordering': ['-created_at'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='Application',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('status', models.CharField(choices=[('preparing', 'Voorbereiden'), ('applied', 'Verzonden'), ('interview', 'Gesprek'), ('offer', 'Aanbod'), ('rejected', 'Afgewezen'), ('withdrawn', 'Ingetrokken')], default='preparing', max_length=20)),
|
|
('applied_at', models.DateTimeField(blank=True, null=True)),
|
|
('follow_up_date', models.DateField(blank=True, null=True)),
|
|
('contact_name', models.CharField(blank=True, max_length=200)),
|
|
('contact_email', models.EmailField(blank=True, max_length=254)),
|
|
('notes', models.TextField(blank=True)),
|
|
('document_manifest', models.JSONField(blank=True, default=list)),
|
|
('snapshot', models.JSONField(blank=True, default=dict)),
|
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
|
('job', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='applications', to='jobs.jobposting')),
|
|
],
|
|
options={
|
|
'ordering': ['-updated_at'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='JobSourceAlias',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('url', models.URLField(max_length=2000)),
|
|
('canonical_url', models.URLField(db_index=True, max_length=2000)),
|
|
('external_id', models.CharField(blank=True, db_index=True, max_length=500)),
|
|
('source_title', models.CharField(blank=True, max_length=500)),
|
|
('source_employer', models.CharField(blank=True, max_length=300)),
|
|
('extraction_method', models.CharField(blank=True, max_length=120)),
|
|
('extraction_confidence', models.DecimalField(decimal_places=3, default=0.5, max_digits=4)),
|
|
('first_seen', models.DateTimeField(default=django.utils.timezone.now)),
|
|
('last_seen', models.DateTimeField(default=django.utils.timezone.now)),
|
|
('is_canonical', models.BooleanField(default=False)),
|
|
('payload', models.JSONField(blank=True, default=dict)),
|
|
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='source_aliases', to='jobs.jobposting')),
|
|
('raw_document', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='job_aliases', to='sources.rawdocument')),
|
|
('source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='job_aliases', to='sources.source')),
|
|
],
|
|
options={
|
|
'ordering': ['-is_canonical', '-last_seen'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='FieldProvenance',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('field_name', models.CharField(max_length=120)),
|
|
('extraction_method', models.CharField(max_length=120)),
|
|
('confidence', models.DecimalField(decimal_places=3, default=0.5, max_digits=4)),
|
|
('evidence_excerpt', models.CharField(blank=True, max_length=1000)),
|
|
('parser_version', models.CharField(blank=True, max_length=80)),
|
|
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='provenance', to='jobs.jobposting')),
|
|
('source_alias', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='field_evidence', to='jobs.jobsourcealias')),
|
|
],
|
|
options={
|
|
'ordering': ['field_name', '-confidence'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='JobVersion',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('content_hash', models.CharField(max_length=64)),
|
|
('snapshot', models.JSONField(default=dict)),
|
|
('changed_fields', models.JSONField(blank=True, default=list)),
|
|
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='jobs.jobposting')),
|
|
],
|
|
options={
|
|
'ordering': ['-created_at'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='ScoreRun',
|
|
fields=[
|
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
('updated_at', models.DateTimeField(auto_now=True)),
|
|
('profile_version', models.PositiveIntegerField()),
|
|
('score', models.DecimalField(decimal_places=2, max_digits=5)),
|
|
('confidence', models.DecimalField(decimal_places=3, max_digits=4)),
|
|
('recommendation', models.CharField(choices=[('strong', 'Sterke match'), ('possible', 'Mogelijke match'), ('weak', 'Lage match'), ('hidden', 'Verborgen')], max_length=16)),
|
|
('components', models.JSONField(default=dict)),
|
|
('positives', models.JSONField(default=list)),
|
|
('concerns', models.JSONField(default=list)),
|
|
('hard_exclusions', models.JSONField(default=list)),
|
|
('evidence', models.JSONField(blank=True, default=dict)),
|
|
('model_version', models.CharField(blank=True, max_length=120)),
|
|
('prompt_version', models.CharField(blank=True, max_length=120)),
|
|
('job', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scores', to='jobs.jobposting')),
|
|
('profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='scores', to='profiles.searchprofile')),
|
|
],
|
|
options={
|
|
'ordering': ['-created_at'],
|
|
},
|
|
),
|
|
migrations.AddIndex(
|
|
model_name='jobposting',
|
|
index=models.Index(fields=['normalized_title', 'region'], name='jobs_jobpos_normali_f8851c_idx'),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name='jobposting',
|
|
index=models.Index(fields=['status', 'valid_through'], name='jobs_jobpos_status_4c49ee_idx'),
|
|
),
|
|
migrations.AddConstraint(
|
|
model_name='application',
|
|
constraint=models.UniqueConstraint(fields=('user', 'job'), name='unique_application_per_user_job'),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name='jobsourcealias',
|
|
index=models.Index(fields=['source', 'external_id'], name='jobs_jobsou_source__66ce6b_idx'),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name='jobsourcealias',
|
|
index=models.Index(fields=['canonical_url'], name='jobs_jobsou_canonic_9fd8cb_idx'),
|
|
),
|
|
migrations.AddConstraint(
|
|
model_name='jobversion',
|
|
constraint=models.UniqueConstraint(fields=('job', 'content_hash'), name='unique_job_content_version'),
|
|
),
|
|
migrations.AddIndex(
|
|
model_name='scorerun',
|
|
index=models.Index(fields=['profile', '-score', '-created_at'], name='jobs_scorer_profile_5fca7f_idx'),
|
|
),
|
|
]
|