Files
Hulumath-Web/backend/content/services.py
T
Jacky 1f98f7152d
CI / test (push) Failing after 1m31s
v0.2 Preview: Construction Plan.
2026-08-08 21:25:27 +08:00

69 lines
2.3 KiB
Python

from django.db import transaction
from django.utils import timezone
from rest_framework.exceptions import ValidationError
from progression.models import RewardTransaction, UserAbility
from .models import ContentInteraction, ContentItem, VideoProgress
ABILITY_TO_DIMENSION = {
ContentItem.Ability.VISION: UserAbility.Dimension.VISION,
ContentItem.Ability.HUMANITIES: UserAbility.Dimension.HUMANITIES,
ContentItem.Ability.DETECTION: UserAbility.Dimension.DETECTION,
ContentItem.Ability.MODELING: UserAbility.Dimension.MODELING,
ContentItem.Ability.CONNECTION: UserAbility.Dimension.CONNECTION,
}
@transaction.atomic
def complete_video(user, content):
if content.kind != ContentItem.Kind.VIDEO:
raise ValidationError("只有视频内容可以提交观看完成")
progress, _ = VideoProgress.objects.select_for_update().get_or_create(
user=user,
content=content,
)
progress.position_seconds = max(progress.position_seconds, content.duration_seconds)
progress.completed = True
progress.completed_at = progress.completed_at or timezone.now()
reward = None
dimension = ABILITY_TO_DIMENSION.get(content.ability_dimension)
if dimension and not progress.reward_granted:
transaction_key = f"video-complete:{content.id}"
reward_tx, created = RewardTransaction.objects.get_or_create(
user=user,
idempotency_key=transaction_key,
defaults={
"source": "video_complete",
"rewards": {"ability": dimension, "fragments": 1},
},
)
if created:
ability, _ = UserAbility.objects.select_for_update().get_or_create(
user=user,
dimension=dimension,
)
ability.fragments += 1
ability.save(update_fields=["fragments"])
progress.reward_granted = True
reward = reward_tx.rewards
progress.save(
update_fields=[
"position_seconds",
"completed",
"completed_at",
"reward_granted",
"updated_at",
]
)
ContentInteraction.objects.get_or_create(
user=user,
content=content,
action=ContentInteraction.Action.COMPLETE,
)
return progress, reward