class ReviewAction(BaseAction): target = models.ForeignKey('Preprint', related_name='actions', on_delete=models.CASCADE) trigger = models.CharField(max_length=31, choices=ReviewTriggers.choices()) from_state = models.CharField(max_length=31, choices=ReviewStates.choices()) to_state = models.CharField(max_length=31, choices=ReviewStates.choices())
class ReviewableMixin(MachineableMixin): """Something that may be included in a reviewed collection and is subject to a reviews workflow. """ TriggersClass = ReviewTriggers machine_state = models.CharField(max_length=15, db_index=True, choices=ReviewStates.choices(), default=ReviewStates.INITIAL.value) class Meta: abstract = True MachineClass = ReviewsMachine @property def in_public_reviews_state(self): public_states = PUBLIC_STATES.get(self.provider.reviews_workflow) if not public_states: return False return self.machine_state in public_states def run_withdraw(self, user, comment): """Run the 'withdraw' state transition and create a corresponding Action. Params: user: The user triggering this transition. comment: Text describing why. """ return self._run_transition(self.TriggersClass.WITHDRAW.value, user=user, comment=comment)
class ReviewActionSerializer(BaseActionSerializer): class Meta: type_ = 'review-actions' filterable_fields = frozenset([ 'id', 'trigger', 'from_state', 'to_state', 'date_created', 'date_modified', 'provider', 'target', ]) comment = HideIfProviderCommentsPrivate( ser.CharField(max_length=65535, required=False)) trigger = ser.ChoiceField(choices=ReviewTriggers.choices()) from_state = ser.ChoiceField(choices=ReviewStates.choices(), read_only=True) to_state = ser.ChoiceField(choices=ReviewStates.choices(), read_only=True) provider = RelationshipField( read_only=True, related_view='providers:preprint-providers:preprint-provider-detail', related_view_kwargs={'provider_id': '<target.provider._id>'}, filter_key='target__provider___id', ) creator = HideIfProviderCommentsAnonymous( RelationshipField( read_only=True, related_view='users:user-detail', related_view_kwargs={'user_id': '<creator._id>'}, filter_key='creator__guids___id', always_embed=True, )) target = TargetRelationshipField( target_class=PreprintService, read_only=False, required=True, related_view='preprints:preprint-detail', related_view_kwargs={'preprint_id': '<target._id>'}, filter_key='target__guids___id', ) def create(self, validated_data): trigger = validated_data.get('trigger') if trigger != ReviewTriggers.WITHDRAW.value: return super(ReviewActionSerializer, self).create(validated_data) user = validated_data.pop('user') target = validated_data.pop('target') comment = validated_data.pop('comment', '') try: return target.run_withdraw(user=user, comment=comment) except InvalidTriggerError as e: # Invalid transition from the current state raise Conflict(e.message) else: raise JSONAPIAttributeException(attribute='trigger', detail='Invalid trigger.')