@@ -0,0 +1,104 @@
|
||||
from django.db import transaction
|
||||
from django.utils import timezone
|
||||
|
||||
from content.models import ContentInteraction, ContentItem
|
||||
from math_life.models import (
|
||||
MathBTIAssessment,
|
||||
MathBTIResult,
|
||||
MathIdentity,
|
||||
Story,
|
||||
StoryRun,
|
||||
StoryVersion,
|
||||
)
|
||||
from math_life.services import score_mathbti
|
||||
from progression.models import Card, UserCard
|
||||
from progression.services import initialize_math_identity
|
||||
|
||||
from .models import VisitorMigration
|
||||
|
||||
|
||||
def migration_summary(payload):
|
||||
mathbti = 1 if isinstance(payload.get("mathbti"), dict) else 0
|
||||
return {
|
||||
"mathbti_results": mathbti,
|
||||
"story_saves": min(len(payload.get("story_saves", [])), 20),
|
||||
"favorites": min(len(payload.get("favorites", [])), 200),
|
||||
"cards": min(len(payload.get("cards", [])), 100),
|
||||
}
|
||||
|
||||
|
||||
@transaction.atomic
|
||||
def apply_visitor_migration(user):
|
||||
migration = VisitorMigration.objects.select_for_update().get(user=user)
|
||||
if migration.status == VisitorMigration.Status.APPLIED:
|
||||
return migration
|
||||
|
||||
payload = migration.payload
|
||||
mathbti = payload.get("mathbti")
|
||||
if isinstance(mathbti, dict):
|
||||
assessment = MathBTIAssessment.objects.filter(
|
||||
version=mathbti.get("version"),
|
||||
is_published=True,
|
||||
).first()
|
||||
if assessment:
|
||||
code, scores = score_mathbti(assessment.definition, mathbti.get("answers", []))
|
||||
identity = MathIdentity.objects.get(code=code)
|
||||
MathBTIResult.objects.create(
|
||||
user=user,
|
||||
assessment=assessment,
|
||||
identity=identity,
|
||||
answers=mathbti["answers"],
|
||||
axis_scores=scores,
|
||||
)
|
||||
initialize_math_identity(user, identity)
|
||||
|
||||
for item in payload.get("story_saves", [])[:20]:
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
story = Story.objects.filter(slug=item.get("story_slug")).first()
|
||||
if story is None:
|
||||
continue
|
||||
version = StoryVersion.objects.filter(
|
||||
story=story,
|
||||
version=item.get("version"),
|
||||
is_published=True,
|
||||
).first()
|
||||
node_id = item.get("current_node")
|
||||
if version is None or node_id not in version.content.get("nodes", {}):
|
||||
continue
|
||||
StoryRun.objects.get_or_create(
|
||||
user=user,
|
||||
story_version=version,
|
||||
status=StoryRun.Status.ACTIVE,
|
||||
defaults={
|
||||
"current_node": node_id,
|
||||
"state": item.get("state", {}) if isinstance(item.get("state"), dict) else {},
|
||||
},
|
||||
)
|
||||
|
||||
favorites = ContentItem.objects.filter(
|
||||
slug__in=payload.get("favorites", [])[:200],
|
||||
is_published=True,
|
||||
)
|
||||
ContentInteraction.objects.bulk_create(
|
||||
[
|
||||
ContentInteraction(
|
||||
user=user,
|
||||
content=item,
|
||||
action=ContentInteraction.Action.FAVORITE,
|
||||
)
|
||||
for item in favorites
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
cards = Card.objects.filter(slug__in=payload.get("cards", [])[:100])
|
||||
UserCard.objects.bulk_create(
|
||||
[UserCard(user=user, card=card, source="visitor_migration") for card in cards],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
migration.status = VisitorMigration.Status.APPLIED
|
||||
migration.applied_at = timezone.now()
|
||||
migration.save(update_fields=["status", "applied_at"])
|
||||
return migration
|
||||
Reference in New Issue
Block a user