class SimpleActivitySerializer(serializers.ModelSerializer): action = serializers.CharField(source='verb') activity_type = serializers.SerializerMethodField() activity = GenericRelatedField( { get_user_model(): SimpleUserSerializer(), Channel: ChannelSerializer(), ChannelUser: ChannelUserSerializer(), Message: MessageSerializer(), Comment: CommentSerializer(), Upload: UploadSerializer(), Connection: ConnectionSerializer(), Task: SimpleTaskSerializer(), Application: ApplicationSerializer(), Participation: ParticipationSerializer(), Estimate: SimpleEstimateSerializer(), Quote: SimpleQuoteSerializer(), ProgressEvent: SimpleProgressEventSerializer(), ProgressReport: ProgressReportSerializer(), Integration: SimpleIntegrationSerializer(), IntegrationActivity: SimpleIntegrationActivitySerializer() }, source='action_object') class Meta: model = Action exclude = ('verb', 'actor_object_id', 'actor_content_type', 'action_object_object_id', 'action_object_content_type', 'target_object_id', 'target_content_type') def get_activity_type(self, obj): return get_instance_type(obj.action_object)
class CommentSerializer(serializers.ModelSerializer): user = SimpleUserSerializer(required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) uploads = UploadSerializer(read_only=True, required=False, many=True) class Meta: model = Comment read_only_fields = ('created_at', )
class CommentSerializer(serializers.ModelSerializer): user = SimplestUserSerializer(required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) uploads = UploadSerializer(read_only=True, required=False, many=True) text_body = serializers.CharField(required=False, read_only=True) html_body = serializers.CharField(required=False, read_only=True) class Meta: model = Comment fields = '__all__' read_only_fields = ('created_at',)
class MessageSerializer(serializers.ModelSerializer, GetCurrentUserAnnotatedSerializerMixin): user = SimplestUserSerializer(required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) excerpt = serializers.CharField(required=False, read_only=True) attachments = UploadSerializer(read_only=True, required=False, many=True) sender = SenderSerializer(read_only=True, required=False) text_body = serializers.CharField(required=False, read_only=True) html_body = serializers.CharField(required=False, read_only=True) class Meta: model = Message exclude = ('alt_user', 'source', 'extra') read_only_fields = ('created_at',)
class ProgressReportSerializer(ContentTypeAnnotatedModelSerializer, DetailAnnotatedModelSerializer): user = serializers.PrimaryKeyRelatedField( required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) status_display = serializers.CharField(required=False, read_only=True, source='get_status_display') uploads = UploadSerializer(required=False, read_only=True, many=True) class Meta: model = ProgressReport read_only_fields = ('created_at', ) details_serializer = ProgressReportDetailsSerializer
class ActivitySerializer(SimpleActivitySerializer): actor_type = serializers.SerializerMethodField() target_type = serializers.SerializerMethodField() actor = GenericRelatedField({ get_user_model(): SimpleUserSerializer(), Integration: SimpleIntegrationSerializer() }) target = GenericRelatedField({ get_user_model(): SimpleUserSerializer(), Channel: ChannelSerializer(), ChannelUser: ChannelUserSerializer(), Message: MessageSerializer(), Comment: CommentSerializer(), Upload: UploadSerializer(), Connection: ConnectionSerializer(), Task: SimpleTaskSerializer(), Application: ApplicationSerializer(), Participation: ParticipationSerializer(), ProgressEvent: SimpleProgressEventSerializer(), ProgressReport: SimpleProgressReportSerializer(), Integration: SimpleIntegrationSerializer(), IntegrationActivity: SimpleIntegrationActivitySerializer() }) class Meta(SimpleActivitySerializer.Meta): fields = '__all__' exclude = None def get_actor_type(self, obj): return get_instance_type(obj.actor) def get_target_type(self, obj): return get_instance_type(obj.target)
class SimpleProgressReportSerializer(BasicProgressReportSerializer): uploads = UploadSerializer(required=False, read_only=True, many=True) class Meta: model = ProgressReport
class TaskSerializer(ContentTypeAnnotatedModelSerializer, DetailAnnotatedModelSerializer, GetCurrentUserAnnotatedSerializerMixin): user = serializers.PrimaryKeyRelatedField( required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) display_fee = serializers.SerializerMethodField(required=False, read_only=True) excerpt = serializers.CharField(required=False, read_only=True) skills = serializers.CharField(required=True, allow_blank=True, allow_null=True) deadline = serializers.DateTimeField(required=False, allow_null=True) can_apply = serializers.SerializerMethodField(read_only=True, required=False) can_save = serializers.SerializerMethodField(read_only=True, required=False) is_participant = serializers.SerializerMethodField(read_only=True, required=False) my_participation = serializers.SerializerMethodField(read_only=True, required=False) summary = serializers.CharField(read_only=True, required=False) assignee = BasicParticipationSerializer(required=False, read_only=True) participants = serializers.PrimaryKeyRelatedField( many=True, queryset=get_user_model().objects.all(), required=False, write_only=True) open_applications = serializers.SerializerMethodField(required=False, read_only=True) update_schedule_display = serializers.CharField(required=False, read_only=True) participation = NestedTaskParticipationSerializer(required=False, read_only=False, many=True) milestones = NestedProgressEventSerializer(required=False, read_only=False, many=True) progress_events = NestedProgressEventSerializer(required=False, read_only=True, many=True) ratings = SimpleRatingSerializer(required=False, read_only=False, many=True) uploads = UploadSerializer(required=False, read_only=True, many=True) all_uploads = UploadSerializer(required=False, read_only=True, many=True) class Meta: model = Task exclude = ('applicants', ) read_only_fields = ('created_at', ) details_serializer = TaskDetailsSerializer def create(self, validated_data): skills = None participation = None milestones = None participants = None ratings = None if 'skills' in validated_data: skills = validated_data.pop('skills') if 'participation' in validated_data: participation = validated_data.pop('participation') if 'milestones' in validated_data: milestones = validated_data.pop('milestones') if 'participants' in validated_data: participants = validated_data.pop('participants') if 'ratings' in validated_data: ratings = validated_data.pop('ratings') if participation or participants: # close applications if paticipants are provided validated_data['apply'] = False instance = super(TaskSerializer, self).create(validated_data) self.save_skills(instance, skills) self.save_participants(instance, participants) self.save_participation(instance, participation) self.save_milestones(instance, milestones) self.save_ratings(instance, ratings) # Triggered here instead of in the post_save signal to allow skills to be attached first # TODO: Consider moving this trigger send_new_task_email.delay(instance.id) return instance def update(self, instance, validated_data): initial_apply = instance.apply initial_closed = instance.closed skills = None participation = None milestones = None participants = None ratings = None if 'skills' in validated_data: skills = validated_data.pop('skills') if 'participation' in validated_data: participation = validated_data.pop('participation') if 'milestones' in validated_data: milestones = validated_data.pop('milestones') if 'participants' in validated_data: participants = validated_data.pop('participants') if 'ratings' in validated_data: ratings = validated_data.pop('ratings') if not instance.closed and validated_data.get('closed'): validated_data['closed_at'] = datetime.datetime.utcnow() if not instance.paid and validated_data.get('paid'): validated_data['paid_at'] = datetime.datetime.utcnow() instance = super(TaskSerializer, self).update(instance, validated_data) self.save_skills(instance, skills) self.save_participants(instance, participants) self.save_participation(instance, participation) self.save_milestones(instance, milestones) self.save_ratings(instance, ratings) if initial_apply and not instance.apply: task_applications_closed.send(sender=Task, task=instance) if not initial_closed and instance.closed: task_closed.send(sender=Task, task=instance) return instance def save_skills(self, task, skills): if skills is not None: task.skills = skills task.save() def save_participation(self, task, participation): if participation: new_assignee = None for item in participation: if item.get('accepted', False): item['activated_at'] = datetime.datetime.utcnow() try: Participation.objects.update_or_create(task=task, user=item['user'], defaults=item) if 'assignee' in item and item['assignee']: new_assignee = item['user'] except: pass if new_assignee: Participation.objects.exclude(user=new_assignee).filter( task=task).update(assignee=False) def save_milestones(self, task, milestones): if milestones: for item in milestones: event_type = item.get('type', PROGRESS_EVENT_TYPE_MILESTONE) if event_type != PROGRESS_EVENT_TYPE_MILESTONE: continue defaults = {'created_by': self.get_current_user() or task.user} defaults.update(item) try: ProgressEvent.objects.update_or_create( task=task, type=event_type, due_at=item['due_at'], defaults=defaults) except: pass def save_ratings(self, task, ratings): if ratings: for item in ratings: try: Rating.objects.update_or_create( content_type=ContentType.objects.get_for_model(task), object_id=task.id, criteria=item['criteria'], defaults=item) except: pass def save_participants(self, task, participants): # TODO: Remove and move existing code to using save_participation if participants: assignee = self.initial_data.get('assignee', None) confirmed_participants = self.initial_data.get( 'confirmed_participants', None) rejected_participants = self.initial_data.get( 'rejected_participants', None) created_by = self.get_current_user() if not created_by: created_by = task.user changed_assignee = False for user in participants: try: defaults = {'created_by': created_by} if assignee: defaults['assignee'] = bool(user.id == assignee) if rejected_participants and user.id in rejected_participants: defaults['accepted'] = False defaults['responded'] = True if confirmed_participants and user.id in confirmed_participants: defaults['accepted'] = True defaults['responded'] = True defaults['activated_at'] = datetime.datetime.utcnow() Participation.objects.update_or_create(task=task, user=user, defaults=defaults) if user.id == assignee: changed_assignee = True except: pass if assignee and changed_assignee: Participation.objects.exclude(user__id=assignee).filter( task=task).update(assignee=False) def get_display_fee(self, obj): user = self.get_current_user() amount = None if user and user.is_developer: amount = obj.fee * (1 - TUNGA_SHARE_PERCENTAGE * 0.01) return obj.display_fee(amount=amount) def get_can_apply(self, obj): if obj.closed or not obj.apply: return False user = self.get_current_user() if user: if obj.user == user or user.pending: return False return obj.applicants.filter(id=user.id).count() == 0 and \ obj.participation_set.filter(user=user).count() == 0 return False def get_can_save(self, obj): user = self.get_current_user() if user: if obj.user == user: return False return obj.savedtask_set.filter(user=user).count() == 0 return False def get_is_participant(self, obj): user = self.get_current_user() if user: return obj.participation_set.filter( (Q(accepted=True) | Q(responded=False)), user=user).count() == 1 return False def get_my_participation(self, obj): user = self.get_current_user() if user: try: participation = obj.participation_set.get(user=user) return { 'id': participation.id, 'user': participation.user.id, 'assignee': participation.assignee, 'accepted': participation.accepted, 'responded': participation.responded } except: pass return None def get_open_applications(self, obj): return obj.application_set.filter(responded=False).count()
class ChannelSerializer(DetailAnnotatedModelSerializer, GetCurrentUserAnnotatedSerializerMixin): created_by = SimpleUserSerializer(required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) display_type = serializers.CharField(required=False, read_only=True, source='get_type_display') participants = serializers.PrimaryKeyRelatedField( required=True, many=True, queryset=get_user_model().objects.all()) attachments = UploadSerializer(read_only=True, required=False, many=True, source='all_attachments') user = serializers.SerializerMethodField(read_only=True, required=False) new_messages = serializers.IntegerField(read_only=True, required=False) new = serializers.SerializerMethodField(read_only=True, required=False) last_read = serializers.SerializerMethodField(read_only=True, required=False) alt_subject = serializers.CharField(required=False, read_only=True, source='get_alt_subject') class Meta: model = Channel exclude = () read_only_fields = ('created_at', 'type') details_serializer = ChannelDetailsSerializer def validate_participants(self, value): error = 'Select some participants for this conversation' if not isinstance(value, list) or not value: raise ValidationError(error) participants = self.clean_participants(value) if not participants: raise ValidationError(error) return value def create(self, validated_data): participants = None if 'participants' in validated_data: participants = validated_data.pop('participants') participants = self.clean_participants(participants) subject = validated_data.get('subject', None) if not subject and isinstance(participants, list) and len(participants) == 1: # Create or get a direct channel # if only one other participant is given and no subject is stated for the communication current_user = self.get_current_user() channel = get_or_create_direct_channel(current_user, participants[0]) else: #if not subject: # raise ValidationError({'subject': 'Enter a subject for this conversation'}) channel = Channel.objects.create(**validated_data) self.save_participants(channel, participants) return channel def update(self, instance, validated_data): participants = None if 'participants' in validated_data: participants = validated_data.pop('participants') participants = self.clean_participants(participants) for attr, value in validated_data.items(): setattr(instance, attr, value) subject = validated_data.get('subject', None) if not subject and isinstance(participants, list) and len(participants) > 1: raise ValidationError( {'subject': 'Enter a subject for this conversation'}) instance.save() self.save_participants(instance, participants) return instance def clean_participants(self, participants): current_user = self.get_current_user() if isinstance(participants, (list, tuple)) and current_user: return [ user_id for user_id in participants if user_id != current_user.id ] return participants def save_participants(self, instance, participants): if participants: participants.append(instance.created_by) for user in participants: try: ChannelUser.objects.update_or_create(channel=instance, user=user) except: pass def get_user(self, obj): current_user = self.get_current_user() if current_user: receiver = obj.get_receiver(current_user) if receiver: return SimpleUserSerializer(receiver).data return None def get_new(self, obj): user = self.get_current_user() if user: return channel_activity_new_messages_filter( queryset=obj.target_actions.filter( channels__channeluser__user=user), user=user).count() return 0 def get_last_read(self, obj): user = self.get_current_user() if user: try: return obj.channeluser_set.get(user=user).last_read except: pass else: return obj.last_read return 0
def get_uploads(self, obj): content_type = ContentType.objects.get_for_model(Comment) uploads = Upload.objects.filter(content_type=content_type, object_id=obj.id) return UploadSerializer(uploads, many=True).data
class TaskSerializer(ContentTypeAnnotatedModelSerializer, DetailAnnotatedModelSerializer, GetCurrentUserAnnotatedSerializerMixin): user = SimpleUserSerializer(required=False, read_only=True, default=CreateOnlyCurrentUserDefault()) pay = serializers.DecimalField(max_digits=19, decimal_places=4, required=False, read_only=True) display_fee = serializers.SerializerMethodField(required=False, read_only=True) amount = serializers.JSONField(required=False, read_only=True) is_payable = serializers.BooleanField(required=False, read_only=True) is_project = serializers.BooleanField(required=False, read_only=True) is_task = serializers.BooleanField(required=False, read_only=True) is_developer_ready = serializers.BooleanField(required=False, read_only=True) requires_estimate = serializers.BooleanField(required=False, read_only=True) excerpt = serializers.CharField(required=False, read_only=True) skills = serializers.CharField( required=False, error_messages={ 'blank': 'Please specify the skills required for this task' }) payment_status = serializers.CharField(required=False, read_only=True) deadline = serializers.DateTimeField(required=False, allow_null=True) can_apply = serializers.SerializerMethodField(read_only=True, required=False) can_claim = serializers.SerializerMethodField(read_only=True, required=False) can_return = serializers.SerializerMethodField(read_only=True, required=False) can_save = serializers.SerializerMethodField(read_only=True, required=False) is_participant = serializers.SerializerMethodField(read_only=True, required=False) is_admin = serializers.SerializerMethodField(read_only=True, required=False) my_participation = serializers.SerializerMethodField(read_only=True, required=False) summary = serializers.CharField(read_only=True, required=False) assignee = SimpleParticipationSerializer(required=False, read_only=True) participants = serializers.PrimaryKeyRelatedField( many=True, queryset=get_user_model().objects.all(), required=False, write_only=True) update_schedule_display = serializers.CharField(required=False, read_only=True) participation = NestedTaskParticipationSerializer(required=False, read_only=False, many=True) milestones = NestedProgressEventSerializer(required=False, read_only=False, many=True) progress_events = NestedProgressEventSerializer(required=False, read_only=True, many=True) ratings = SimpleRatingSerializer(required=False, read_only=False, many=True) uploads = UploadSerializer(required=False, read_only=True, many=True) all_uploads = UploadSerializer(required=False, read_only=True, many=True) invoice = TaskInvoiceSerializer(required=False, read_only=True) estimate = SimpleEstimateSerializer(required=False, read_only=True) quote = SimpleQuoteSerializer(required=False, read_only=True) pm = SimpleUserSerializer(required=False, read_only=True) class Meta: model = Task exclude = ('applicants', ) read_only_fields = ('created_at', 'paid', 'paid_at', 'invoice_date', 'btc_address', 'btc_price', 'pay_distributed') extra_kwargs = { 'type': { 'required': True, 'allow_blank': False, 'allow_null': False }, 'scope': { 'required': True, 'allow_blank': False, 'allow_null': False } } details_serializer = TaskDetailsSerializer def validate(self, attrs): has_parent = attrs.get('parent', None) or (self.instance and self.instance.parent) scope = attrs.get('scope', None) or (self.instance and self.instance.scope) is_project = attrs.get( 'is_project', None) or (self.instance and self.instance.is_project) has_requirements = attrs.get( 'is_project', None) or (self.instance and self.instance.has_requirements) coders_needed = attrs.get('coders_needed', None) pm_required = attrs.get('pm_required', None) fee = attrs.get('fee', None) title = attrs.get('title', None) skills = attrs.get('skills', None) visibility = attrs.get('visibility', None) description = attrs.get('description', None) email = self.initial_data.get('email', None) first_name = self.initial_data.get('first_name', None) last_name = self.initial_data.get('last_name', None) current_user = self.get_current_user() errors = dict() if current_user and current_user.is_authenticated(): if scope == TASK_SCOPE_TASK or has_parent: if not has_parent and fee: MinValueValidator( 15, message='Minimum pledge amount is EUR 15')(fee) if not title and not self.partial: errors.update({'title': 'This field is required.'}) if not description and not self.partial: errors.update({'description': 'This field is required.'}) if not skills and not self.partial: errors.update({'skills': 'This field is required.'}) if visibility == VISIBILITY_CUSTOM and not ( attrs.get('participation', None) or attrs.get('participants', None)): errors.update({ 'visibility': 'Please choose at least one developer for this task' }) if scope == TASK_SCOPE_TASK and description and self.partial and len( description.split(' ')) <= 15: errors.update({ 'description': 'Please provide a more detailed description.' }) if scope == TASK_SCOPE_ONGOING: if not skills and not self.partial: errors.update({'skills': 'This field is required.'}) if not coders_needed and not self.partial: errors.update({'coders_needed': 'This field is required.'}) if scope == TASK_SCOPE_PROJECT: if not title and not self.partial: errors.update({'title': 'This field is required.'}) if not skills and not self.partial: errors.update({'skills': 'This field is required.'}) if not pm_required and not self.partial: errors.update({'pm_required': 'This field is required.'}) else: if not description: errors.update({'description': 'This field is required.'}) if email: try: get_user_model().objects.get(email=email) errors.update({ 'form': 'Looks like you already have a Tunga account. Please login to create new tasks.', 'email': 'This email address is already attached to an account on Tunga' }) except get_user_model().DoesNotExist: pass else: errors.update({'email': 'This field is required.'}) if not first_name: errors.update({'first_name': 'This field is required.'}) if not last_name: errors.update({'last_name': 'This field is required.'}) if errors: raise ValidationError(errors) return attrs def save_task(self, validated_data, instance=None): current_user = self.get_current_user() if current_user and current_user.is_authenticated( ) and not instance and not profile_check(current_user): ValidationError( 'You need complete your profile before you can post tasks') if instance and 'fee' in validated_data and validated_data[ 'fee'] < instance.fee: raise ValidationError({ 'fee': 'You cannot reduce the fee for the task, Please contact [email protected] for assistance' }) skills = None participation = None milestones = None participants = None ratings = None if 'skills' in validated_data: skills = validated_data.pop('skills') if 'participation' in validated_data: participation = validated_data.pop('participation') if 'milestones' in validated_data: milestones = validated_data.pop('milestones') if 'participants' in validated_data: participants = validated_data.pop('participants') if 'ratings' in validated_data: ratings = validated_data.pop('ratings') initial_apply = True initial_closed = False initial_approved = False new_user = None is_update = bool(instance) if instance: initial_apply = instance.apply initial_closed = instance.closed initial_approved = instance.approved if not instance.closed and validated_data.get('closed'): validated_data['closed_at'] = datetime.datetime.utcnow() if not instance.paid and validated_data.get('paid'): validated_data['paid_at'] = datetime.datetime.utcnow() instance = super(TaskSerializer, self).update(instance, validated_data) else: if not current_user or not current_user.is_authenticated(): validated_data['source'] = TASK_SOURCE_NEW_USER if participation or participants: # Close applications if paticipants are provided when creating task validated_data['apply'] = False validated_data['apply_closed_at'] = datetime.datetime.utcnow() if not current_user or not current_user.is_authenticated(): # Create user and add them as the creator or task, indicate if task was unauthenticated email = self.initial_data.get('email', None) first_name = self.initial_data.get('first_name', None) last_name = self.initial_data.get('last_name', None) new_user = get_user_model().objects.create_user( username=email, email=email, password=get_user_model().objects.make_random_password(), first_name=first_name, last_name=last_name, type=USER_TYPE_PROJECT_OWNER, source=USER_SOURCE_TASK_WIZARD) if new_user: validated_data.update({'user': new_user}) user_signed_up.send(sender=get_user_model(), request=None, user=new_user) instance = super(TaskSerializer, self).create(validated_data) self.save_skills(instance, skills) self.save_participants(instance, participants) self.save_participation(instance, participation) self.save_milestones(instance, milestones) self.save_ratings(instance, ratings) if is_update: if not initial_approved and instance.approved: task_approved.send(sender=Task, task=instance) if initial_apply and not instance.apply: task_applications_closed.send(sender=Task, task=instance) if not initial_closed and instance.closed: task_closed.send(sender=Task, task=instance) else: # Triggered here instead of in the post_save signal to allow skills to be attached first # TODO: Consider moving this trigger notify_new_task.delay(instance.id, new_user=bool(new_user)) return instance def create(self, validated_data): return self.save_task(validated_data) def update(self, instance, validated_data): return self.save_task(validated_data, instance=instance) def save_skills(self, task, skills): if skills is not None: task.skills = skills task.save() def save_participation(self, task, participation): if participation: new_assignee = None for item in participation: if 'accepted' in item and item.get('accepted', False): item['activated_at'] = datetime.datetime.utcnow() defaults = item if isinstance(defaults, dict): current_user = self.get_current_user() participation_creator = task.user if current_user and current_user.is_authenticated( ) and current_user != item.get('user', None): participation_creator = current_user defaults['created_by'] = participation_creator try: participation_obj, created = Participation.objects.update_or_create( task=task, user=item['user'], defaults=defaults) if (not created) and 'accepted' in item: participation_response.send( sender=Participation, participation=participation_obj) if 'assignee' in item and item['assignee']: new_assignee = item['user'] except: pass if new_assignee: Participation.objects.exclude(user=new_assignee).filter( task=task).update(assignee=False) def save_milestones(self, task, milestones): if milestones: for item in milestones: event_type = item.get('type', PROGRESS_EVENT_TYPE_MILESTONE) if event_type != PROGRESS_EVENT_TYPE_MILESTONE: continue defaults = {'created_by': self.get_current_user() or task.user} defaults.update(item) try: ProgressEvent.objects.update_or_create( task=task, type=event_type, due_at=item['due_at'], defaults=defaults) except: pass def save_ratings(self, task, ratings): if ratings: for item in ratings: try: Rating.objects.update_or_create( content_type=ContentType.objects.get_for_model(task), object_id=task.id, criteria=item['criteria'], defaults=item) except: pass def save_participants(self, task, participants): # TODO: Remove and move existing code to using save_participation if participants: assignee = self.initial_data.get('assignee', None) confirmed_participants = self.initial_data.get( 'confirmed_participants', None) rejected_participants = self.initial_data.get( 'rejected_participants', None) created_by = self.get_current_user() or task.user changed_assignee = False for user in participants: try: defaults = {'created_by': created_by} if assignee: defaults['assignee'] = bool(user.id == assignee) if rejected_participants and user.id in rejected_participants: defaults['accepted'] = False defaults['responded'] = True if confirmed_participants and user.id in confirmed_participants: defaults['accepted'] = True defaults['responded'] = True defaults['activated_at'] = datetime.datetime.utcnow() participation_obj, created = Participation.objects.update_or_create( task=task, user=user, defaults=defaults) if (not created) and (user.id in rejected_participants or user.id in confirmed_participants): participation_response.send( sender=Participation, participation=participation_obj) if user.id == assignee: changed_assignee = True except: pass if assignee and changed_assignee: Participation.objects.exclude(user__id=assignee).filter( task=task).update(assignee=False) def get_display_fee(self, obj): user = self.get_current_user() amount = None if not obj.pay: return None if user and user.is_developer: amount = obj.pay_dev * (1 - obj.tunga_ratio_dev) return obj.display_fee(amount=amount) def get_can_apply(self, obj): if obj.closed or not obj.apply or not obj.is_developer_ready: return False user = self.get_current_user() if user: if obj.user == user or not user.is_developer or user.pending or not profile_check( user): return False return obj.applicants.filter(id=user.id).count() == 0 and \ obj.participation_set.filter(user=user).count() == 0 return False def get_can_claim(self, obj): if obj.closed or obj.is_task: return False user = self.get_current_user() if user and user.is_authenticated() and ( user.is_project_manager or user.is_admin) and not obj.pm and ( obj.pm_required or obj.source == TASK_SOURCE_NEW_USER): return True return False def get_can_return(self, obj): if obj.closed or obj.estimate: return False user = self.get_current_user() if user and user.is_authenticated() and obj.pm == user: return True return False def get_can_save(self, obj): return False def get_is_participant(self, obj): user = self.get_current_user() if user: return obj.subtask_participants_inclusive_filter.filter( (Q(accepted=True) | Q(responded=False)), user=user).count() > 0 return False def get_is_admin(self, obj): user = self.get_current_user() return obj.has_admin_access(user) def get_my_participation(self, obj): user = self.get_current_user() if user: try: participation = obj.participation_set.get(user=user) return { 'id': participation.id, 'user': participation.user.id, 'assignee': participation.assignee, 'accepted': participation.accepted, 'responded': participation.responded } except: pass return None