class Gift(ContributorModel): """ Gift model """ objects = GiftQuerySet.as_manager() customer = fields.OneToOneField( Customer, on_delete=models.CASCADE, ) is_active = fields.BooleanField( default=True, help_text='This flag is used to determine that customer gift is active' 'or not. `True` is active; otherwise, `False`.') def __str__(self): return f'gift:{self.id}'
class Reward(ContributorModel): """ Reward model """ objects = RewardQuerySet.as_manager() membership = fields.OneToOneField( Membership, on_delete=models.CASCADE, null=True, blank=True, ) is_active = fields.BooleanField( default=True, help_text='A flag for marking that reward is active or not', ) def __str__(self): return f'reward:{self.id}'
class GiftItem(ContributorModel): """ Gift Item model """ objects = GiftItemQuerySet.as_manager() product = fields.OneToOneField( Product, on_delete=models.CASCADE, ) gift = fields.ForeignKey( Gift, on_delete=models.CASCADE, ) quantity = fields.IntegerField( verbose_name='Number of item', default=0, validators=[MinValueValidator(0)], )
class Transaction(ContributorModel): """ Transaction model """ objects = TransactionQuerySet.as_manager() order = fields.OneToOneField( Order, on_delete=models.CASCADE, help_text='The order which transaction belong to', ) user = fields.ForeignKey( 'accounts.User', on_delete=models.CASCADE, help_text='The user who own this transaction', ) coupon = fields.ForeignKey( Coupon, on_delete=models.CASCADE, null=True, blank=True, ) total_amount = fields.FloatField( default=0, validators=[MinValueValidator(0)], help_text='Total amount of an order', ) total_pay_amount = fields.FloatField( default=0, validators=[MinValueValidator(0)], help_text='The actual amount that customer need to pay', ) earning_point = fields.IntegerField( validators=[MinValueValidator(0)], default=0, help_text='Number of point of an order that customer earns', ) burning_point = fields.IntegerField( validators=[MinValueValidator(0)], default=0, help_text='Number of point that customer spend to redeem product', )
class Customer(ContributorModel): """ Customer model. """ objects = CustomerQuerySet.as_manager() name = fields.ShortNameField(verbose_name='Customer name', ) account = fields.OneToOneField( 'accounts.User', on_delete=models.CASCADE, ) membership = fields.ForeignKey( Membership, on_delete=models.CASCADE, null=True, blank=True, ) email = models.OneToOneField( Email, on_delete=models.CASCADE, ) phone_number = fields.PhoneNumberField() available_point = fields.IntegerField( help_text='Current point', default=0, null=False, blank=False, validators=[MinValueValidator(0)], ) total_earned_point = fields.IntegerField( help_text='Total earned point from the beginning', default=0, null=False, blank=False, validators=[MinValueValidator(0)], ) is_active = models.BooleanField( help_text='Indicate that customer is active or not. ' 'True if active; otherwise, False', default=True, ) def __str__(self): return f'customer: {self.id}' def clean(self): """ Don't allow `total_earned_point` is less than `available_point` """ if self.total_earned_point < self.available_point: total_earned_point_msg = '`total_earned_point` must be greater ' \ 'than or equal `available_point`' available_point_msg = '`available_point` must be less ' \ 'than or equal `total_earned_point`' raise ValidationError({ 'total_earned_point': ValidationError(_(total_earned_point_msg)), 'available_point': ValidationError(_(available_point_msg)) }) def save(self, **kwargs): """ Save the customer information. Check and set membership level for customer based on the total earned point. """ try: level_obj = MembershipLevel.objects.filter( require_point__lte=self.total_earned_point).order_by( '-require_point').first() if level_obj: if self.membership: self.membership.level = level_obj self.membership.save() else: level_filtered = Membership.objects.filter(level=level_obj)\ .first() self.membership = level_filtered if level_filtered else \ Membership.objects.create(level=level_obj) super(Customer, self).save(**kwargs) except Exception as e: raise e