github.com/ismailbayram/bigpicture@v0.0.0-20231225173155-e4b21f5efcff/internal/browser/pyproject/baskets/service.py (about)

     1  from decimal import Decimal
     2  from django.utils.translation import ugettext_lazy as _
     3  
     4  from django.db.models import Q, F
     5  from django.db.transaction import atomic
     6  
     7  from baskets.models import Basket, BasketItem, Campaign
     8  from baskets.enums import BasketStatus
     9  from baskets.exceptions import (PrimaryProductsQuantityMustOne,
    10                                  BasketInvalidException,
    11                                  BasketEmptyException,
    12                                  BasketAmountLessThanZeroException)
    13  from cars.exceptions import CustomerHasNoSelectedCarException
    14  import cars.*
    15  
    16  
    17  class BasketService:
    18      def get_or_create_basket(self, customer_profile):
    19          """
    20          :param customer_profile: CustomerProfile
    21          :return: Basket
    22          """
    23          if not customer_profile.selected_car:
    24              raise CustomerHasNoSelectedCarException
    25          try:
    26              basket = Basket.objects.get(customer_profile=customer_profile,
    27                                          status=BasketStatus.active,
    28                                          car=customer_profile.selected_car)
    29              self._check_basket_items(basket)
    30          except Basket.DoesNotExist:
    31              basket = Basket.objects.create(customer_profile=customer_profile,
    32                                             status=BasketStatus.active,
    33                                             car=customer_profile.selected_car)
    34          return basket
    35  
    36      def apply_discounts(self, basket):
    37          """
    38          :param basket: Basket
    39          :return: Basket
    40          """
    41          self.clean_discounts(basket)
    42          campaigns = Campaign.objects.actives()
    43          for campaign in campaigns:
    44              strategy = campaign.promotion_type.get_strategy(campaign=campaign,
    45                                                              basket=basket)
    46              if strategy.check():
    47                  strategy.apply()
    48              else:
    49                  message = campaign.message.format(**{'remaining': strategy.remaining})
    50                  basket.campaign_messages.append(message)
    51          return basket
    52  
    53      def _check_basket_items(self, basket):
    54          """
    55          :param basket: Basket
    56          :return: bool
    57          """
    58          invalid_items = basket.basketitem_set.exclude(product__is_active=True,
    59                                                        product__store__is_active=True,
    60                                                        product__store__is_approved=True)
    61          if invalid_items:
    62              msg = _('Some services that are invalid have been removed from your basket: ')
    63  
    64              for bi in invalid_items:
    65                  msg += bi.product.name + ', '
    66                  bi.delete()
    67  
    68              basket.warning_messages.append(msg)
    69  
    70          return not invalid_items.exists()
    71  
    72      def add_basket_item(self, basket, product):
    73          """
    74          :param basket: Basket
    75          :param product: Product
    76          :return: BasketItem
    77          """
    78          if not basket.is_empty and basket.basketitem_set.filter(~Q(product__store=product.store)).exists():
    79              self.clean_basket(basket)
    80  
    81          try:
    82              basket_item = basket.basketitem_set.get(product=product)
    83              if basket_item.product.is_primary:
    84                  raise PrimaryProductsQuantityMustOne
    85              basket_item.quantity = F('quantity') + 1
    86              basket_item.save()
    87          except BasketItem.DoesNotExist:
    88              primary_count = basket.basketitem_set.filter(product__is_primary=True).count()
    89              if primary_count > 0 and product.is_primary:
    90                  raise PrimaryProductsQuantityMustOne
    91              basket_item = BasketItem.objects.create(basket=basket, product=product)
    92  
    93          self._check_basket_items(basket)
    94          return basket_item
    95  
    96      def clean_discounts(self, basket):
    97          """
    98          :param basket: Basket
    99          :return: basket
   100          """
   101          basket.campaign_messages = []
   102          basket.discountitem_set.all().delete()
   103          return basket
   104  
   105      def clean_basket(self, basket):
   106          """
   107          :param basket: Basket
   108          :return: Basket
   109          """
   110          basket.basketitem_set.all().delete()
   111          self.clean_discounts(basket)
   112          return basket
   113  
   114      def delete_basket_item(self, basket, product):
   115          """
   116          :param basket: Basket
   117          :param product: Product
   118          :return: None
   119          """
   120          basket.basketitem_set.filter(product=product).delete()
   121          self._check_basket_items(basket)
   122  
   123      @atomic
   124      def complete_basket(self, basket):
   125          """
   126          :param basket: Basket
   127          :return: Basket
   128          """
   129          if basket.is_empty:
   130              raise BasketEmptyException
   131          is_basket_valid = self._check_basket_items(basket)
   132          if not is_basket_valid:
   133              raise BasketInvalidException
   134          if basket.get_net_amount() < Decimal('0.00'):
   135              raise BasketAmountLessThanZeroException
   136  
   137          for bi in basket.basketitem_set.all():
   138              bi.amount = bi.get_price()
   139              bi.save()
   140          basket.status = BasketStatus.completed
   141          basket.save()
   142  
   143          return basket
   144  
   145      def _create_quotation_items(self, quotation: Quotation | Order, basket_items: list[BasketItem]) -> None:
   146          QuotationItem.objects.bulk_create(
   147              [
   148                  QuotationItem(
   149                      quotation=quotation,
   150                      product_remote_id=bi.product_remote_id,
   151                      quantity=bi.quantity,
   152                      division=bi.division,
   153                      price=bi.price,
   154                      data=bi.data,
   155                      currency=bi.currency,
   156                  )
   157                  for bi in basket_items
   158              ]
   159          )