# 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'), ), ]