@@ -0,0 +1,68 @@
|
||||
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
|
||||
Reference in New Issue
Block a user