diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 08f5252..2b7c80f 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/migrations/0003_identityprofile_entity_profile.py b/core/migrations/0003_identityprofile_entity_profile.py new file mode 100644 index 0000000..208ae32 --- /dev/null +++ b/core/migrations/0003_identityprofile_entity_profile.py @@ -0,0 +1,30 @@ +# Generated by Django 5.2.7 on 2026-03-22 22:49 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0002_relationship'), + ] + + operations = [ + migrations.CreateModel( + name='IdentityProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('full_name', models.CharField(max_length=255)), + ('description', models.TextField(blank=True)), + ('profile_image_url', models.URLField(blank=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ], + ), + migrations.AddField( + model_name='entity', + name='profile', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='entities', to='core.identityprofile'), + ), + ] diff --git a/core/migrations/__pycache__/0003_identityprofile_entity_profile.cpython-311.pyc b/core/migrations/__pycache__/0003_identityprofile_entity_profile.cpython-311.pyc new file mode 100644 index 0000000..de7a389 Binary files /dev/null and b/core/migrations/__pycache__/0003_identityprofile_entity_profile.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 9a1dbe1..5c5187c 100644 --- a/core/models.py +++ b/core/models.py @@ -8,6 +8,19 @@ class Source(models.Model): def __str__(self): return self.name +class IdentityProfile(models.Model): + """ + Groups various entities (Person, Email, Username, etc.) into a single identity profile. + """ + full_name = models.CharField(max_length=255) + description = models.TextField(blank=True) + profile_image_url = models.URLField(blank=True) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.full_name + class Entity(models.Model): ENTITY_TYPES = ( ('PERSON', 'Person'), @@ -18,6 +31,7 @@ class Entity(models.Model): entity_type = models.CharField(max_length=20, choices=ENTITY_TYPES) value = models.CharField(max_length=255, db_index=True) source = models.ForeignKey(Source, on_delete=models.CASCADE, related_name='entities') + profile = models.ForeignKey(IdentityProfile, on_delete=models.SET_NULL, null=True, blank=True, related_name='entities') confidence_score = models.FloatField(default=1.0) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) @@ -45,4 +59,4 @@ class Relationship(models.Model): unique_together = ('source_entity', 'target_entity', 'relationship_type') def __str__(self): - return f"{self.source_entity} -[{self.relationship_type}]-> {self.target_entity}" + return f"{self.source_entity} -[{self.relationship_type}]-> {self.target_entity}" \ No newline at end of file diff --git a/core/services/__pycache__/ingestion.cpython-311.pyc b/core/services/__pycache__/ingestion.cpython-311.pyc index 0363eac..b9ff004 100644 Binary files a/core/services/__pycache__/ingestion.cpython-311.pyc and b/core/services/__pycache__/ingestion.cpython-311.pyc differ diff --git a/core/services/ingestion.py b/core/services/ingestion.py index 0ccf613..590b014 100644 --- a/core/services/ingestion.py +++ b/core/services/ingestion.py @@ -1,30 +1,31 @@ from django.db import transaction -from core.models import Source, Entity +from core.models import Source, Entity, IdentityProfile class IngestionService: @staticmethod - def ingest_data(source_name, entity_type, raw_data): + def ingest_data(source_name, entity_type, value, profile_data=None): """ - Aggregates and normalizes raw data into the system. + Aggregates and normalizes data into the system, optionally linking it to an IdentityProfile. """ with transaction.atomic(): source, _ = Source.objects.get_or_create(name=source_name) - # Simple normalization logic: assume raw_data is a dict - # In a real scenario, this would be more complex depending on source schema - identifier = raw_data.get('identifier') - if not identifier: - raise ValueError("Missing identifier in raw_data") + profile = None + if profile_data: + profile, _ = IdentityProfile.objects.get_or_create( + full_name=profile_data.get('full_name', 'Unknown'), + defaults={'description': profile_data.get('description', '')} + ) entity, created = Entity.objects.get_or_create( - identifier=identifier, entity_type=entity_type, - defaults={'source': source, 'metadata': raw_data.get('metadata', {})} + value=value, + source=source, + defaults={'profile': profile} ) - if not created: - # Update existing entity metadata - entity.metadata.update(raw_data.get('metadata', {})) + if not created and profile: + entity.profile = profile entity.save() - return entity + return entity \ No newline at end of file diff --git a/core/templates/core/dashboard.html b/core/templates/core/dashboard.html index b88362d..63f8cea 100644 --- a/core/templates/core/dashboard.html +++ b/core/templates/core/dashboard.html @@ -2,17 +2,63 @@ {% block content %}