Skip to content

Commit 6a6efd2

Browse files
committed
Saving analysis and migrating from logs
1 parent ddb4b4b commit 6a6efd2

4 files changed

Lines changed: 57 additions & 4 deletions

File tree

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.16 on 2026-02-21 02:48
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('map_projects', '0028_auto_20260211_1447'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='mapproject',
15+
name='analysis',
16+
field=models.JSONField(blank=True, default=dict, null=True),
17+
),
18+
]
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Generated by Django 4.2.16 on 2026-02-21 02:50
2+
3+
from django.db import migrations
4+
from pydash import get
5+
6+
7+
def populate_analysis_from_row_logs(apps, schema_editor):
8+
MapProject = apps.get_model('map_projects', 'MapProject')
9+
for map_project in MapProject.objects.all():
10+
analysis = {}
11+
if map_project.logs and not map_project.analysis:
12+
for row_id, logs in map_project.logs.get('row_logs', {}).items():
13+
ai_log = next((log for log in sorted(logs, key=lambda log: log.get('created_at', ''), reverse=True) if get(log, 'action') == 'AIRecommendation'), False)
14+
if ai_log and not get(ai_log, 'extras.error'):
15+
response = get(ai_log, 'extras')
16+
response['model'] = get(response, 'model.id') or 'anthropic/claude-haiku-4.5'
17+
response['timestamp'] = get(ai_log, 'created_at')
18+
response['user'] = get(ai_log, 'user')
19+
analysis[row_id] = response
20+
if analysis:
21+
map_project.analysis = analysis
22+
map_project.save(update_fields=['analysis'])
23+
24+
25+
class Migration(migrations.Migration):
26+
27+
dependencies = [
28+
('map_projects', '0029_mapproject_analysis'),
29+
]
30+
31+
operations = [
32+
migrations.RunPython(populate_analysis_from_row_logs),
33+
]

core/map_projects/models.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class MapProject(BaseModel):
3737
filters = models.JSONField(default=dict, null=True, blank=True)
3838
candidates = models.JSONField(default=dict, null=True, blank=True)
3939
lookup_config = models.JSONField(default=dict, null=True, blank=True)
40+
analysis = models.JSONField(default=dict, null=True, blank=True)
4041

4142
class Meta:
4243
db_table = 'map_projects'
@@ -159,13 +160,14 @@ def _delete_uploaded_file(file_path):
159160
def format_request_data(cls, data, parent_resource=None):
160161
new_data = {
161162
key: val[0] if isinstance(val, list) and len(val) == 1 and key not in [
162-
'candidates'] else val for key, val in data.items()
163+
'candidates', 'analysis'] else val for key, val in data.items()
163164
}
164165
cls.format_json(new_data, 'matches')
165166
cls.format_json(new_data, 'columns')
166167
cls.format_json(new_data, 'score_configuration')
167168
cls.format_json(new_data, 'filters')
168169
cls.format_json(new_data, 'candidates')
170+
cls.format_json(new_data, 'analysis')
169171
cls.format_json(new_data, 'algorithms')
170172
cls.format_json(new_data, 'lookup_config')
171173

core/map_projects/serializers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Meta:
2222
'created_by', 'updated_by', 'created_at', 'updated_at', 'url', 'is_active',
2323
'public_access', 'file', 'user_id', 'organization_id', 'description',
2424
'target_repo_url', 'include_retired', 'score_configuration',
25-
'filters', 'candidates', 'algorithms', 'lookup_config'
25+
'filters', 'candidates', 'algorithms', 'lookup_config', 'analysis'
2626
]
2727

2828
def prepare_object(self, validated_data, instance=None, file=None):
@@ -36,7 +36,7 @@ def prepare_object(self, validated_data, instance=None, file=None):
3636
instance.columns = columns
3737
for attr in [
3838
'name', 'description', 'extras', 'target_repo_url', 'include_retired',
39-
'score_configuration', 'filters', 'candidates', 'algorithms', 'lookup_config'
39+
'score_configuration', 'filters', 'candidates', 'algorithms', 'lookup_config', 'analysis'
4040
]:
4141
setattr(instance, attr, validated_data.get(attr, get(instance, attr)))
4242
if not instance.id:
@@ -109,7 +109,7 @@ class Meta:
109109
'created_by', 'updated_by', 'created_at', 'updated_at', 'url', 'is_active',
110110
'owner', 'owner_type', 'owner_url', 'public_access',
111111
'target_repo_url', 'summary', 'logs', 'include_retired',
112-
'score_configuration', 'filters', 'candidates', 'algorithms', 'lookup_config'
112+
'score_configuration', 'filters', 'candidates', 'algorithms', 'lookup_config', 'analysis'
113113
]
114114

115115
def __init__(self, *args, **kwargs):

0 commit comments

Comments
 (0)