105 lines
3.4 KiB
Python
105 lines
3.4 KiB
Python
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
|