Пример #1
0
class Shippable(TimestampedModel):
    """Add this to every shippable item"""
    name = models.CharField(max_length=255)
    name_receipt = models.CharField(
        _('Name for receipts'),
        max_length=255,
        help_text=
        '«посещение мастер-класса по TDD» или «Доступ к записи курсов кройки и шитья»'
    )
    full_name = models.CharField(
        _('Full name for letters'),
        max_length=255,
        help_text=
        'Билет на мастер-класс о TDD или «запись курсов кройки и шитья»',
    )
    slug = models.SlugField()

    price = models.DecimalField(max_digits=8, decimal_places=2)
    old_price = models.DecimalField(max_digits=8,
                                    decimal_places=2,
                                    blank=True,
                                    null=True)

    tinkoff_credit_promo_code = models.CharField(
        _('Fixed promo code for tinkoff credit'),
        max_length=64,
        blank=True,
        help_text=_('Used in tinkoff credit only'))

    class Meta:
        abstract = True

    def get_price_display(self):
        return format_price(self.price)

    def get_old_price_display(self):
        return format_price(self.old_price)

    def get_formatted_price_display(self):
        return format_old_price(self.old_price, self.price)

    def ship(self, to: User, order: Optional[Order] = None):
        return ShippingFactory.ship(self, to=to, order=order)

    def get_price(self, promocode=None) -> Decimal:
        promocode = apps.get_model('orders.PromoCode').objects.get_or_nothing(
            name=promocode)

        if promocode is not None:
            return promocode.apply(self.price)

        return self.price

    def get_template_id(self):
        """Get custom per-item template_id"""
        if not hasattr(self, 'template_id'):
            return

        if self.template_id is not None and len(self.template_id):
            return self.template_id
Пример #2
0
class Recipe(TimestampedModel):
    name = models.CharField(_("Name"),
                            max_length=255,
                            db_index=True,
                            unique=True)

    cement_weight = models.DecimalField(_("Cement, kg"),
                                        max_digits=10,
                                        decimal_places=3,
                                        default=0)
    sand_weight = models.DecimalField(_("Sand, kg"),
                                      max_digits=10,
                                      decimal_places=3,
                                      default=0)
    gravel_weight = models.DecimalField(_("Gravel, kg"),
                                        max_digits=10,
                                        decimal_places=3,
                                        default=0)
    water_weight = models.DecimalField(_("Water, kg"),
                                       max_digits=10,
                                       decimal_places=3,
                                       default=0)
    admixture_weight = models.DecimalField(_("Admixture, kg"),
                                           max_digits=10,
                                           decimal_places=3,
                                           default=0)

    class Meta:
        verbose_name = _("Recipe")
        verbose_name_plural = _("Recipes")

    def __str__(self):
        return self.name
Пример #3
0
class Shippable(TimestampedModel):
    """Add this to every shippable item"""
    name = models.CharField(max_length=255)
    name_receipt = models.CharField(
        _('Name for receipts'),
        max_length=255,
        help_text=
        '«посещение мастер-класса по TDD» или «Доступ к записи курсов кройки и шитья»'
    )
    full_name = models.CharField(
        _('Full name for letters'),
        max_length=255,
        help_text=
        'Билет на мастер-класс о TDD или «запись курсов кройки и шитья»',
    )
    slug = models.SlugField()

    price = models.DecimalField(max_digits=8, decimal_places=2)
    old_price = models.DecimalField(max_digits=8,
                                    decimal_places=2,
                                    blank=True,
                                    null=True)

    class Meta:
        abstract = True

    def get_price_display(self):
        return format_price(self.price)

    def get_old_price_display(self):
        return format_price(self.old_price)

    def get_formatted_price_display(self):
        return format_old_price(self.old_price, self.price)

    def ship(self, to):
        return ShippingFactory.ship(self, to=to)

    def get_template_id(self):
        """Get custom per-item template_id"""
        if not hasattr(self, 'template_id'):
            return

        if self.template_id is not None and len(self.template_id):
            return self.template_id
Пример #4
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)
Пример #5
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)
Пример #6
0
class Batch(TimestampedModel):
    recipe = models.ForeignKey("lab.recipe",
                               verbose_name=_("Recipe"),
                               on_delete=models.PROTECT)
    volume = models.DecimalField(_("Volume, m3"),
                                 max_digits=10,
                                 decimal_places=3,
                                 default=0)

    cement_weight = models.DecimalField(_("Cement, kg"),
                                        max_digits=10,
                                        decimal_places=3,
                                        default=0)
    sand_weight = models.DecimalField(_("Sand, kg"),
                                      max_digits=10,
                                      decimal_places=3,
                                      default=0)
    gravel_weight = models.DecimalField(_("Gravel, kg"),
                                        max_digits=10,
                                        decimal_places=3,
                                        default=0)
    water_weight = models.DecimalField(_("Water, kg"),
                                       max_digits=10,
                                       decimal_places=3,
                                       default=0)
    admixture_weight = models.DecimalField(_("Admixture, kg"),
                                           max_digits=10,
                                           decimal_places=3,
                                           default=0)

    class Meta:
        verbose_name = _("Batch")
        verbose_name_plural = _("Batches")

    def __str__(self):
        return f"{self.recipe.name}: {self.volume} м3"
Пример #7
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,
        )
Пример #8
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)()