예제 #1
0
class Answer(TreeNode):
    objects: AnswerQuerySet = AnswerQuerySet.as_manager()

    created = models.DateTimeField(auto_now_add=True, db_index=True)
    modified = models.DateTimeField(null=True, blank=True, db_index=True)

    slug = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4)
    question = models.ForeignKey('homework.Question', on_delete=models.CASCADE)
    author = models.ForeignKey('users.User', on_delete=models.CASCADE)

    text = MarkdownxField()

    class Meta:
        verbose_name = _('Homework answer')
        verbose_name_plural = _('Homework answers')
        ordering = ['created']
        permissions = [
            ('see_all_answers', _('May see answers from every user')),
        ]

    def save(self, *args, **kwargs):
        if self.pk:
            self.modified = timezone.now()

        return super().save(*args, **kwargs)
예제 #2
0
class Answer(TreeNode):
    objects: AnswerQuerySet = AnswerQuerySet.as_manager()

    created = models.DateTimeField(auto_now_add=True, db_index=True)
    modified = models.DateTimeField(auto_now=True, db_index=True)

    slug = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4)
    question = models.ForeignKey('homework.Question', on_delete=models.CASCADE)
    author = models.ForeignKey('users.User', on_delete=models.CASCADE)
    do_not_crosscheck = models.BooleanField(_('Exclude from cross-checking'),
                                            default=False)

    text = MarkdownxField()

    class Meta:
        verbose_name = _('Homework answer')
        verbose_name_plural = _('Homework answers')
        ordering = ['created']
        permissions = [
            ('see_all_answers', _('May see answers from every user')),
        ]

    def get_root_answer(self):
        ancesorts = self.ancestors()
        if ancesorts.count():
            return ancesorts[0]

        return self

    def get_absolute_url(self):
        root = self.get_root_answer()

        url = urljoin(settings.FRONTEND_URL, f'homework/answers/{root.slug}/')

        if root != self:
            url = f'{url}#{self.slug}'  # append hash with current answer id

        return url

    def get_purchased_course(self):
        latest_purchase = Order.objects.paid().filter(
            user=self.author,
            course__in=self.question.courses.all()).order_by('-paid').first()

        if latest_purchase:
            return latest_purchase.course

    def get_first_level_descendants(self):
        return self.descendants().filter(parent=self.id)

    def __str__(self):
        LENGTH = 30
        text = self.text[:LENGTH]
        if len(text) == LENGTH:
            text += '...'

        return text
예제 #3
0
class PasswordlessAuthToken(TimestampedModel):
    objects = PasswordlessAuthTokenQuerySet.as_manager()

    user = models.ForeignKey('users.User', on_delete=models.CASCADE)
    token = models.UUIDField(default=uuid.uuid4, unique=True, db_index=True)
    expires = models.DateTimeField(default=default_expiration)
    used = models.DateTimeField(null=True)

    def get_absolute_url(self):
        return urljoin(settings.FRONTEND_URL,
                       '/'.join(['auth', 'passwordless',
                                 str(self.token), '']))

    def mark_as_used(self):
        if not settings.DANGEROUSLY_MAKE_ONE_TIME_PASSWORDLESS_TOKEN_MULTI_PASS:
            self.used = timezone.now()
            self.save()
예제 #4
0
class Token(TimestampedModel):

    objects = TokenQuerySet.as_manager()  # type: TokenQuerySet

    token = models.CharField(max_length=36,
                             default=uuid.uuid4,
                             unique=True,
                             db_index=True)
    record = models.ForeignKey('courses.Record', on_delete=models.CASCADE)
    expires = models.DateTimeField(blank=True, null=True)

    class Meta:
        verbose_name = _('Onetime token')
        verbose_name_plural = _('Onetime tokens')

    def __str__(self):
        return str(self.token)

    def download(self):
        self.expires = timezone.now() + EXPIRATION_TIME
        self.save()

        return self.record.get_url()
예제 #5
0
class CreditNotification(TimestampedModel):
    """Notification for credit order by TinkoffCredit"""
    STATUSES_CHOICES = (
        ('approved', _('Approved')),
        ('rejected', _('Rejected')),
        ('canceled', _('Canceled')),
        ('signed', _('Signed')),
    )

    order_id = models.IntegerField()
    status = models.CharField(max_length=32, choices=STATUSES_CHOICES)
    bank_created = models.DateTimeField()
    first_payment = models.DecimalField(max_digits=10, decimal_places=2)
    order_amount = models.DecimalField(max_digits=10, decimal_places=2)
    credit_amount = models.DecimalField(max_digits=10, decimal_places=2)
    product = models.CharField(max_length=128)
    term = models.IntegerField()
    monthly_payment = models.DecimalField(max_digits=10, decimal_places=2)
    phone = models.CharField(max_length=64, null=True, blank=True)
    first_name = models.CharField(max_length=128, null=True, blank=True)
    last_name = models.CharField(max_length=128, null=True, blank=True)
    middle_name = models.CharField(max_length=32, blank=True, null=True)
    loan_number = models.CharField(max_length=128, blank=True, null=True)
    email = models.CharField(max_length=128, null=True, blank=True)
예제 #6
0
class Order(TimestampedModel):
    objects = OrderQuerySet.as_manager()  # type: OrderQuerySet

    user = models.ForeignKey('users.User', on_delete=models.PROTECT)
    price = models.DecimalField(max_digits=9, decimal_places=2)
    promocode = models.ForeignKey('orders.PromoCode',
                                  verbose_name=_('Promo Code'),
                                  blank=True,
                                  null=True,
                                  on_delete=models.PROTECT)

    paid = models.DateTimeField(
        _('Date when order got paid'),
        null=True,
        blank=True,
        help_text=_('If set during creation, order automaticaly gets shipped'),
    )
    shipped = models.DateTimeField(_('Date when order was shipped'),
                                   null=True,
                                   blank=True)

    course = ItemField('courses.Course',
                       null=True,
                       blank=True,
                       on_delete=models.PROTECT)
    record = ItemField('courses.Record',
                       null=True,
                       blank=True,
                       on_delete=models.PROTECT)
    bundle = ItemField('courses.Bundle',
                       null=True,
                       blank=True,
                       on_delete=models.PROTECT)

    class Meta:
        ordering = ['-id']
        verbose_name = _('Order')
        verbose_name_plural = _('Orders')

    def __str__(self):
        return f'Order #{self.pk}'

    @property
    def item(self):
        """Find the attached item. Simple replacement for ContentType framework
        """
        for field in self.__class__._meta.get_fields():
            if getattr(field, '_is_item', False):
                if getattr(self, f'{field.name}_id', None) is not None:
                    return getattr(self, field.name)

    @classmethod
    def _iterate_items(cls) -> Iterable[models.fields.Field]:
        for field in cls._meta.get_fields():
            if getattr(field, '_is_item', False):
                yield field

    @classmethod
    def get_item_foreignkey(cls, item) -> Optional[models.fields.Field]:
        """
        Given an item model, returns the ForeignKey to it"""
        for field in cls._iterate_items():
            if field.related_model == item.__class__:
                return field.name

    def reset_items(self):
        for field in self._iterate_items():
            setattr(self, field.name, None)

    def set_item(self, item):
        foreign_key = self.__class__.get_item_foreignkey(item)
        if foreign_key is not None:
            self.reset_items()
            setattr(self, foreign_key, item)
            return

        raise UnknownItemException('There is not foreignKey for {}'.format(
            item.__class__))

    def set_paid(self):
        is_already_paid = self.paid is not None

        self.paid = timezone.now()

        self.save()

        if not is_already_paid and self.item is not None:
            self.ship()

    def ship(self):
        """Ship the order. Better call it asynchronously"""
        self.item.ship(to=self.user)

        self.shipped = timezone.now()

        self.save()

        order_got_shipped.send(
            sender=self.__class__,
            order=self,
        )
예제 #7
0
class Order(TimestampedModel):
    objects = OrderQuerySet.as_manager()  # type: OrderQuerySet

    user = models.ForeignKey('users.User',
                             verbose_name=_('User'),
                             on_delete=models.PROTECT)
    price = models.DecimalField(_('Price'), max_digits=9, decimal_places=2)
    promocode = models.ForeignKey('orders.PromoCode',
                                  verbose_name=_('Promo Code'),
                                  blank=True,
                                  null=True,
                                  on_delete=models.PROTECT)

    paid = models.DateTimeField(
        _('Date when order got paid'),
        null=True,
        blank=True,
        help_text=_('If set during creation, order automaticaly gets shipped'),
    )
    shipped = models.DateTimeField(_('Date when order was shipped'),
                                   null=True,
                                   blank=True)

    desired_bank = models.CharField(_('User-requested bank string'),
                                    blank=True,
                                    max_length=32)

    course = ItemField(to='products.Course',
                       verbose_name=_('Course'),
                       null=True,
                       blank=True,
                       on_delete=models.PROTECT)
    record = ItemField(to='products.Record',
                       verbose_name=_('Record'),
                       null=True,
                       blank=True,
                       on_delete=models.PROTECT)
    bundle = ItemField(to='products.Bundle',
                       verbose_name=_('Bundle'),
                       null=True,
                       blank=True,
                       on_delete=models.PROTECT)

    giver = models.ForeignKey('users.User',
                              verbose_name=_('Giver'),
                              null=True,
                              blank=True,
                              on_delete=models.SET_NULL,
                              related_name='created_gifts')
    desired_shipment_date = models.DateTimeField(
        _('Date when the gift should be shipped'), null=True, blank=True)
    gift_message = models.TextField(_('Gift message'), default='', blank=True)
    notification_to_giver_is_sent = models.BooleanField(default=False)

    class Meta:
        ordering = ['-id']
        verbose_name = _('Order')
        verbose_name_plural = _('Orders')

    def __str__(self):
        return f'Order #{self.pk}'

    @property
    def item(self):
        """Find the attached item. Simple replacement for ContentType framework
        """
        for field in self.__class__._meta.get_fields():
            if getattr(field, '_is_item', False):
                if getattr(self, f'{field.name}_id', None) is not None:
                    return getattr(self, field.name)

    @classmethod
    def _iterate_items(cls) -> Iterable[models.fields.Field]:
        for field in cls._meta.get_fields():
            if getattr(field, '_is_item', False):
                yield field

    @classmethod
    def get_item_foreignkey(cls, item) -> Optional[models.fields.Field]:
        """
        Given an item model, returns the ForeignKey to it"""
        for field in cls._iterate_items():
            if field.related_model == item.__class__:
                return field.name

    def reset_items(self):
        for field in self._iterate_items():
            setattr(self, field.name, None)

    def set_item(self, item):
        foreign_key = self.__class__.get_item_foreignkey(item)
        if foreign_key is not None:
            self.reset_items()
            setattr(self, foreign_key, item)
            return

        raise UnknownItemException('There is not foreignKey for {}'.format(
            item.__class__))

    def set_paid(self, silent=False):
        from orders.services.order_is_paid_setter import Griphook
        Griphook(self, silent=silent)()

    def ship(self, silent: bool = False):
        """Ship the order. Better call it asynchronously"""
        from orders.services.order_shipper import Pigwidgeon
        Pigwidgeon(self, silent=silent)()