コード例 #1
0
class PromoCode(TimestampedModel):
    objects = PromoCodeQuerySet.as_manager()

    name = models.CharField(_('Promo Code'),
                            max_length=32,
                            unique=True,
                            db_index=True)
    discount_percent = models.IntegerField(_('Discount percent'))
    active = models.BooleanField(_('Active'), default=True)
    comment = models.TextField(_('Comment'), blank=True, null=True)

    courses = models.ManyToManyField(
        'products.Course',
        help_text=_('Can not be used for courses not checked here'),
        blank=True)

    class Meta:
        verbose_name = _('Promo Code')
        verbose_name_plural = _('Promo Codes')

    def compatible_with(self, course: Course) -> bool:
        return self.courses.count() == 0 or course in self.courses.all()

    def apply(self, course: Course) -> Decimal:
        if not self.compatible_with(course):
            return course.price

        return Decimal(course.price * (100 - self.discount_percent) / 100)
コード例 #2
0
class User(AbstractUser):
    subscribed = models.BooleanField(_('Subscribed to newsletter'),
                                     default=False)

    @classmethod
    def parse_name(cls, name: str) -> dict:
        if name is None:
            return {}

        parts = name.split(' ', 2)

        if len(parts) == 1:
            return {'first_name': parts[0]}

        if len(parts) == 2:
            return {'first_name': parts[0], 'last_name': parts[1]}

        return {'first_name': parts[0], 'last_name': ' '.join(parts[1:])}

    def __str__(self):
        name = self.first_name + ' ' + self.last_name

        if len(name) < 3:
            return self.username

        return name.strip()
コード例 #3
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
コード例 #4
0
class PromoCode(TimestampedModel):
    objects = PromoCodeQuerySet.as_manager()

    name = models.CharField(_('Promo Code'), max_length=32, unique=True, db_index=True)
    discount_percent = models.IntegerField(_('Discount percent'))
    active = models.BooleanField(_('Active'), default=True)
    comment = models.TextField(_('Comment'), blank=True, null=True)

    class Meta:
        verbose_name = _('Promo Code')
        verbose_name_plural = _('Promo Codes')

    def apply(self, price: Decimal) -> Decimal:
        return Decimal(price * (100 - self.discount_percent) / 100)
コード例 #5
0
class User(AbstractUser):
    subscribed = models.BooleanField(_('Subscribed to newsletter'),
                                     default=False)
    first_name_en = models.CharField(_('first name in english'),
                                     max_length=150,
                                     blank=True)
    last_name_en = models.CharField(_('last name in english'),
                                    max_length=150,
                                    blank=True)
    uuid = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4)

    @classmethod
    def parse_name(cls, name: str) -> dict:
        if name is None:
            return {}

        parts = name.split(' ', 2)

        if len(parts) == 1:
            return {'first_name': parts[0]}

        if len(parts) == 2:
            return {'first_name': parts[0], 'last_name': parts[1]}

        return {'first_name': parts[0], 'last_name': ' '.join(parts[1:])}

    def __str__(self):
        name = self.first_name + ' ' + self.last_name

        if len(name) < 3:
            return self.username

        return name.strip()

    def add_perm(self, perm):
        """Add permission to the user.
        This is a shortcut method for testing, please do not use in production
        """
        [app_label, model, codename] = perm.split('.')

        permission = Permission.objects.get_by_natural_key(
            codename, app_label, model)
        if permission is not None:
            self.user_permissions.add(permission)
コード例 #6
0
class PaymentNotification(TimestampedModel):
    STATUS_CHOICES = (
        ('AUTHORIZED', _('Authorized')),
        ('CONFIRMED', _('Confirmed')),
        ('REVERSED', _('Reversed')),
        ('REFUNDED', _('Refunded')),
        ('PARTIAL_REFUNDED', _('Partial refunded')),
        ('REJECTED', _('Rejected')),
    )

    terminal_key = models.CharField(max_length=512)
    order_id = models.IntegerField()
    success = models.BooleanField()
    status = models.CharField(max_length=128, choices=STATUS_CHOICES)
    payment_id = models.BigIntegerField()
    error_code = models.CharField(max_length=512, null=True)
    amount = models.DecimalField(decimal_places=2, max_digits=9)
    rebill_id = models.BigIntegerField(null=True)
    card_id = models.CharField(null=True, max_length=64)
    pan = models.CharField(max_length=128, null=True)
    data = models.TextField(null=True)
    token = models.CharField(max_length=512)
    exp_date = models.CharField(max_length=32, null=True)
コード例 #7
0
ファイル: order.py プロジェクト: yakimka/education-backend
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)()