コード例 #1
0
ファイル: test_cart.py プロジェクト: Maxence42/balafon
    def test_post_cart_not_available(self):
        """It should create a new sale and ignore articles which are not available"""

        # Create contact for the user
        profile = create_profile_contact(self.user)
        contact = profile.contact

        store_item1 = mommy.make(models.StoreItem, stock_count=Decimal('10'))
        store_item2 = mommy.make(models.StoreItem, stock_count=Decimal('0.5'), available=False)

        delivery_point = mommy.make(models.DeliveryPoint)

        data = {
            'items': [
                {'id': store_item1.id, 'quantity': 2},
                {'id': store_item2.id, 'quantity': 1},
            ],
            'delivery_point': delivery_point.id,
            'purchase_datetime': datetime(2015, 7, 23, 12, 0)
        }

        url = reverse('store_post_cart')

        response = self.client.post(url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.assertEqual(response.data['ok'], True)
        self.assertEqual(len(response.data['warnings']), 1)
        self.assertEqual(response.data['deliveryDate'], data['purchase_datetime'])
        self.assertEqual(response.data['deliveryPlace'], delivery_point.name)

        action_type = ActionType.objects.get(name=get_cart_type_name())

        action_queryset = Action.objects.filter(type=action_type)
        self.assertEqual(action_queryset.count(), 1)
        action = action_queryset[0]

        self.assertEqual(list(action.contacts.all()), [contact])
        self.assertEqual(action.subject, '')
        self.assertEqual(action.detail, '')
        self.assertEqual(action.planned_date, data['purchase_datetime'])

        self.assertEqual(action.sale.saleitem_set.count(), 1)
        self.assertEqual(action.sale.saleitem_set.all()[0].item, store_item1)
        self.assertEqual(action.sale.saleitem_set.all()[0].text, store_item1.name)
        self.assertEqual(action.sale.saleitem_set.all()[0].unit_price(), store_item1.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[0].vat_rate, store_item1.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[0].quantity, 2)

        self.assertEqual(len(mail.outbox), 2)
        self.assertEqual(mail.outbox[0].to, [profile.contact.email])
        self.assertEqual(mail.outbox[1].to, [settings.BALAFON_NOTIFICATION_EMAIL])

        store_item1 = models.StoreItem.objects.get(id=store_item1.id)
        self.assertEqual(store_item1.stock_count, Decimal("8"))

        store_item2 = models.StoreItem.objects.get(id=store_item2.id)
        self.assertEqual(store_item2.stock_count, Decimal("0.5"))
コード例 #2
0
ファイル: test_cart.py プロジェクト: Maxence42/balafon
    def test_post_cart_notes_several_lines(self):
        """It should create a new sale and action"""

        # Create contact for the user
        profile = create_profile_contact(self.user)
        contact = profile.contact

        store_item1 = mommy.make(models.StoreItem)
        store_item2 = mommy.make(models.StoreItem)

        delivery_point = mommy.make(models.DeliveryPoint)

        data = {
            'items': [
                {'id': store_item1.id, 'quantity': 2},
                {'id': store_item2.id, 'quantity': 1},
            ],
            'delivery_point': delivery_point.id,
            'notes': 'a\nB\nc',
            'purchase_datetime': datetime(2015, 7, 23, 12, 0)
        }

        url = reverse('store_post_cart')

        response = self.client.post(url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.assertEqual(response.data['ok'], True)
        self.assertEqual(len(response.data['warnings']), 0)
        self.assertEqual(response.data['deliveryDate'], data['purchase_datetime'])
        self.assertEqual(response.data['deliveryPlace'], delivery_point.name)

        action_type = ActionType.objects.get(name=get_cart_type_name())

        action_queryset = Action.objects.filter(type=action_type)
        self.assertEqual(action_queryset.count(), 1)
        action = action_queryset[0]

        self.assertEqual(list(action.contacts.all()), [contact])
        self.assertEqual(action.subject, _(u'Notes'))
        self.assertEqual(action.detail, 'a\nB\nc')
        self.assertEqual(action.planned_date, data['purchase_datetime'])

        self.assertEqual(action.sale.saleitem_set.count(), 2)
        self.assertEqual(action.sale.saleitem_set.all()[0].item, store_item1)
        self.assertEqual(action.sale.saleitem_set.all()[0].text, store_item1.name)
        self.assertEqual(action.sale.saleitem_set.all()[0].unit_price(), store_item1.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[0].vat_rate, store_item1.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[0].quantity, 2)

        self.assertEqual(action.sale.saleitem_set.all()[1].item, store_item2)
        self.assertEqual(action.sale.saleitem_set.all()[1].text, store_item2.name)
        self.assertEqual(action.sale.saleitem_set.all()[1].unit_price(), store_item2.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[1].vat_rate, store_item2.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[1].quantity, 1)

        self.assertEqual(len(mail.outbox), 2)
コード例 #3
0
ファイル: test_cart.py プロジェクト: Maxence42/balafon
    def test_post_cart_empty(self):
        """It should create a new sale and ignore articles which are not available"""

        # Create contact for the user
        profile = create_profile_contact(self.user)
        contact = profile.contact

        store_item1 = mommy.make(models.StoreItem, stock_count=Decimal('10'), available=False)
        store_item2 = mommy.make(models.StoreItem, stock_count=Decimal('0.5'), available=False)

        delivery_point = mommy.make(models.DeliveryPoint)

        data = {
            'items': [
                {'id': store_item1.id, 'quantity': 2},
                {'id': store_item2.id, 'quantity': 1},
            ],
            'delivery_point': delivery_point.id,
            'purchase_datetime': datetime(2015, 7, 23, 12, 0)
        }

        url = reverse('store_post_cart')

        response = self.client.post(url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.assertEqual(response.data['ok'], False)
        self.assertEqual(len(response.data['warnings']), 2)

        action_type = ActionType.objects.get(name=get_cart_type_name())

        action_queryset = Action.objects.filter(type=action_type)
        self.assertEqual(action_queryset.count(), 0)

        self.assertEqual(len(mail.outbox), 0)

        store_item1 = models.StoreItem.objects.get(id=store_item1.id)
        self.assertEqual(store_item1.stock_count, Decimal("10"))

        store_item2 = models.StoreItem.objects.get(id=store_item2.id)
        self.assertEqual(store_item2.stock_count, Decimal("0.5"))
コード例 #4
0
ファイル: test_cart.py プロジェクト: Maxence42/balafon
    def test_cart_with_discount(self):
        """The cart should take account discount into account"""

        # Create contact for the user
        profile = create_profile_contact(self.user)
        contact = profile.contact

        discount = mommy.make(
            models.Discount, active=True, name="10% si + de 5", rate=Decimal("10"), quantity=Decimal("5")
        )
        price_class = mommy.make(models.PriceClass, name="Vrac")
        price_class.discounts.add(discount)
        price_class.save()

        store_item1 = mommy.make(models.StoreItem, pre_tax_price=Decimal('10'), price_class=price_class)
        store_item2 = mommy.make(models.StoreItem, pre_tax_price=Decimal('1'), price_class=price_class)
        store_item3 = mommy.make(models.StoreItem, pre_tax_price=Decimal('2'), price_class=None)

        delivery_point = mommy.make(models.DeliveryPoint)

        data = {
            'items': [
                {'id': store_item1.id, 'quantity': 5},
                {'id': store_item2.id, 'quantity': 2},
                {'id': store_item3.id, 'quantity': 5},
            ],
            'delivery_point': delivery_point.id,
            'purchase_datetime': datetime(2015, 7, 23, 12, 0)
        }

        url = reverse('store_post_cart')

        response = self.client.post(url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.assertEqual(response.data['ok'], True)
        self.assertEqual(len(response.data['warnings']), 0)

        action_type = ActionType.objects.get(name=get_cart_type_name())

        action_queryset = Action.objects.filter(type=action_type)
        self.assertEqual(action_queryset.count(), 1)
        action = action_queryset[0]

        self.assertEqual(list(action.contacts.all()), [contact])
        self.assertEqual(action.subject, '')
        self.assertEqual(action.detail, '')
        self.assertEqual(action.planned_date, data['purchase_datetime'])

        self.assertEqual(action.sale.saleitem_set.count(), 3)
        self.assertEqual(action.sale.saleitem_set.all()[0].item, store_item1)
        self.assertEqual(action.sale.saleitem_set.all()[0].text, store_item1.name)
        self.assertEqual(action.sale.saleitem_set.all()[0].unit_price(), store_item1.pre_tax_price * Decimal("0.9"))
        self.assertEqual(action.sale.saleitem_set.all()[0].vat_rate, store_item1.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[0].quantity, 5)

        self.assertEqual(action.sale.saleitem_set.all()[1].item, store_item2)
        self.assertEqual(action.sale.saleitem_set.all()[1].text, store_item2.name)
        self.assertEqual(action.sale.saleitem_set.all()[1].unit_price(), store_item2.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[1].vat_rate, store_item2.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[1].quantity, 2)

        self.assertEqual(action.sale.saleitem_set.all()[2].item, store_item3)
        self.assertEqual(action.sale.saleitem_set.all()[2].text, store_item3.name)
        self.assertEqual(action.sale.saleitem_set.all()[2].unit_price(), store_item3.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[2].vat_rate, store_item3.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[2].quantity, 5)

        self.assertEqual(len(mail.outbox), 2)
        self.assertEqual(mail.outbox[0].to, [profile.contact.email])
        self.assertEqual(mail.outbox[1].to, [settings.BALAFON_NOTIFICATION_EMAIL])
コード例 #5
0
ファイル: test_cart.py プロジェクト: BenjCherpas/balafon
    def test_post_cart_notes_several_lines(self):
        """It should create a new sale and action"""

        # Create contact for the user
        profile = create_profile_contact(self.user)
        contact = profile.contact

        store_item1 = mommy.make(models.StoreItem)
        store_item2 = mommy.make(models.StoreItem)

        delivery_point = mommy.make(models.DeliveryPoint)

        data = {
            'items': [
                {
                    'id': store_item1.id,
                    'quantity': 2
                },
                {
                    'id': store_item2.id,
                    'quantity': 1
                },
            ],
            'delivery_point':
            delivery_point.id,
            'notes':
            'a\nB\nc',
            'purchase_datetime':
            datetime(2015, 7, 23, 12, 0)
        }

        url = reverse('store_post_cart')

        response = self.client.post(url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.assertEqual(response.data['ok'], True)
        self.assertEqual(len(response.data['warnings']), 0)
        self.assertEqual(response.data['deliveryDate'],
                         data['purchase_datetime'])
        self.assertEqual(response.data['deliveryPlace'], delivery_point.name)

        action_type = ActionType.objects.get(name=get_cart_type_name())

        action_queryset = Action.objects.filter(type=action_type)
        self.assertEqual(action_queryset.count(), 1)
        action = action_queryset[0]

        self.assertEqual(list(action.contacts.all()), [contact])
        self.assertEqual(action.subject, _('Notes'))
        self.assertEqual(action.detail, 'a\nB\nc')
        self.assertEqual(action.planned_date, data['purchase_datetime'])

        self.assertEqual(action.sale.saleitem_set.count(), 2)
        self.assertEqual(action.sale.saleitem_set.all()[0].item, store_item1)
        self.assertEqual(action.sale.saleitem_set.all()[0].text,
                         store_item1.name)
        self.assertEqual(action.sale.saleitem_set.all()[0].unit_price(),
                         store_item1.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[0].vat_rate,
                         store_item1.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[0].quantity, 2)

        self.assertEqual(action.sale.saleitem_set.all()[1].item, store_item2)
        self.assertEqual(action.sale.saleitem_set.all()[1].text,
                         store_item2.name)
        self.assertEqual(action.sale.saleitem_set.all()[1].unit_price(),
                         store_item2.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[1].vat_rate,
                         store_item2.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[1].quantity, 1)

        self.assertEqual(len(mail.outbox), 2)
コード例 #6
0
    def post(self, request):
        """receive a new cart"""

        cart_serializer = serializers.CartSerializer(data=request.data)
        if cart_serializer.is_valid():

            # Get Contact
            try:
                profile = ContactProfile.objects.get(user=request.user)
                contact = profile.contact
            except ContactProfile.DoesNotExist:
                return Response({
                    'ok': False,
                    'message': _("You don't have a valid profile")
                })

            # Get Delivery point
            try:
                delivery_point = DeliveryPoint.objects.get(
                    id=cart_serializer.validated_data["delivery_point"])
            except DeliveryPoint.DoesNotExist:
                return Response({
                    'ok': False,
                    'message': _("Invalid delivery point")
                })

            # Create a new Sale
            action_type_name = get_cart_type_name()
            action_type = ActionType.objects.get_or_create(
                name=action_type_name)[0]

            # Force this type to be managed by the store
            StoreManagementActionType.objects.get_or_create(
                action_type=action_type)

            subject = detail = ''
            if 'notes' in cart_serializer.validated_data:
                notes = cart_serializer.validated_data["notes"].strip()
                if notes:
                    subject = _('Notes')
                    detail = notes

            action = Action.objects.create(planned_date=cart_serializer.
                                           validated_data['purchase_datetime'],
                                           subject=subject,
                                           detail=detail,
                                           status=action_type.default_status,
                                           status2=action_type.default_status2,
                                           type=action_type)
            action.contacts.add(contact)
            action.save()

            action.sale.analysis_code = SaleAnalysisCode.objects.get_or_create(
                name="Internet")[0]

            action.sale.delivery_point = delivery_point
            action.sale.save()

            warnings = []
            is_empty = True
            # for each line add a sale item
            for index, item in enumerate(
                    cart_serializer.validated_data['items']):

                quantity = Decimal('{0}'.format(item['quantity']))

                try:
                    store_item = StoreItem.objects.get(id=item['id'])
                except StoreItem.DoesNotExist:
                    # ignore if not existing
                    continue

                if not store_item.available:
                    warnings.append(
                        _("{0} is currently not available. It has been removed from your cart"
                          ).format(store_item.name))
                else:
                    if store_item.stock_count is not None:
                        store_item.stock_count = store_item.stock_count - quantity
                        store_item.save()

                    is_empty = False
                    SaleItem.objects.create(
                        sale=action.sale,
                        quantity=quantity,
                        item=store_item,
                        vat_rate=store_item.vat_rate,
                        pre_tax_price=store_item.pre_tax_price,
                        text=store_item.name,
                        order_index=index + 1)

            # Done
            if is_empty:
                action.delete()

                return Response({
                    'ok':
                    False,
                    'message':
                    _('Your cart is empty. Your articles are not available'),
                    'warnings':
                    warnings,
                })
            else:

                action.sale.save()

                on_cart_processed = get_cart_processed_callback()
                if on_cart_processed:
                    on_cart_processed(action)

                confirm_cart_to_user(profile, action)
                notify_cart_to_admin(profile, action)

                return Response({
                    'ok':
                    True,
                    'warnings':
                    warnings,
                    'deliveryDate':
                    action.planned_date,
                    'deliveryPlace':
                    action.sale.delivery_point.name,
                })
        else:
            return Response({
                'ok':
                False,
                'message':
                ', '.join([
                    '{0}: {1}'.format(*err)
                    for err in cart_serializer.errors.items()
                ])
            })
コード例 #7
0
    def post(self, request):
        """receive a new cart"""

        cart_serializer = self.get_serializer()
        if cart_serializer.is_valid():
            self.cart_serializer = cart_serializer

            discounts = {}
            vat_rates = {}
            voucher_code = cart_serializer.validated_data.get(
                'voucher_code', '')
            voucher = Voucher.get_active_voucher(voucher_code)

            try:
                contact = self.get_buyer_contact()
            except Contact.DoesNotExist as exc:
                return Response({'ok': False, 'message': exc})

            # Get Delivery point
            try:
                delivery_point = DeliveryPoint.objects.get(
                    id=cart_serializer.validated_data["delivery_point"])
            except DeliveryPoint.DoesNotExist:
                return Response({
                    'ok': False,
                    'message': _("Invalid delivery point")
                })

            # Get Payment mode
            payment_mode_id = cart_serializer.validated_data.get(
                'payment_mode')
            if payment_mode_id:
                try:
                    payment_mode = PaymentMode.objects.get(id=payment_mode_id)
                except PaymentMode.DoesNotExist:
                    return Response({
                        'ok': False,
                        'message': _("Invalid payment mode")
                    })
            else:
                payment_mode = None

            # Create a new Sale
            action_type_name = get_cart_type_name()
            action_type = ActionType.objects.get_or_create(
                name=action_type_name)[0]

            # Force this type to be managed by the store
            StoreManagementActionType.objects.get_or_create(
                action_type=action_type)

            subject = detail = ''
            if 'notes' in cart_serializer.validated_data:
                notes = cart_serializer.validated_data["notes"].strip()
                if notes:
                    subject = _('Notes')
                    detail = notes

            action = Action.objects.create(planned_date=cart_serializer.
                                           validated_data['purchase_datetime'],
                                           subject=subject,
                                           detail=detail,
                                           status=action_type.default_status,
                                           status2=action_type.default_status2,
                                           type=action_type)
            action.contacts.add(contact)
            action.save()

            action.sale.analysis_code = SaleAnalysisCode.objects.get_or_create(
                name="Internet")[0]

            action.sale.delivery_point = delivery_point
            action.sale.payment_mode = payment_mode
            action.sale.save()

            warnings = []
            is_empty = True
            # for each line add a sale item
            counter = 0
            for index, item in enumerate(
                    cart_serializer.validated_data['items']):

                quantity = Decimal('{0}'.format(item['quantity']))

                try:
                    store_item = StoreItem.objects.get(id=item['id'])
                except StoreItem.DoesNotExist:
                    # ignore if not existing
                    continue

                if not store_item.available:
                    warnings.append(
                        _("{0} is currently not available. It has been removed from your cart"
                          ).format(store_item.name))
                else:
                    if store_item.stock_count is not None:
                        store_item.stock_count = store_item.stock_count - quantity
                        store_item.save()

                    is_empty = False
                    SaleItem.objects.create(
                        sale=action.sale,
                        quantity=quantity,
                        item=store_item,
                        vat_rate=store_item.vat_rate,
                        pre_tax_price=store_item.pre_tax_price,
                        text=store_item.name,
                        order_index=index + 1)
                    counter = index

                    # calcule s'il y a une réduction Code Promo
                    # Crée une ligne réduction pour ce code
                    if voucher:
                        discount = store_item.pre_tax_price * voucher.rate / 100
                        vat_id = store_item.vat_rate.id if store_item.vat_rate else 0
                        if vat_id not in discounts:
                            vat_rates[vat_id] = store_item.vat_rate
                            discounts[vat_id] = 0
                        discounts[vat_id] += discount * quantity

            for discount_vat, discount_value in discounts.items():
                counter += 1
                SaleItem.objects.create(sale=action.sale,
                                        quantity=1,
                                        item=None,
                                        vat_rate=vat_rates[discount_vat],
                                        pre_tax_price=-discount_value,
                                        text=voucher.label,
                                        order_index=counter,
                                        is_discount=True)

            # Done
            if is_empty:
                action.delete()

                return Response({
                    'ok':
                    False,
                    'message':
                    _('Your cart is empty. Your articles are not available'),
                    'warnings':
                    warnings,
                })
            else:

                action.sale.save()

                on_cart_processed = get_cart_processed_callback()
                if on_cart_processed:
                    on_cart_processed(action)

                notify_cart_callback = get_notify_cart_callback()
                if notify_cart_callback is None:
                    confirm_cart_to_user(contact, action)
                    notify_cart_to_admin(contact, action)
                else:
                    notify_cart_callback(contact, action)

                return Response({
                    'ok':
                    True,
                    'action':
                    action.id,
                    'warnings':
                    warnings,
                    'deliveryDate':
                    action.planned_date,
                    'deliveryPlace':
                    action.sale.delivery_point.name,
                })
        else:
            return Response({
                'ok':
                False,
                'message':
                ', '.join([
                    '{0}: {1}'.format(*err)
                    for err in cart_serializer.errors.items()
                ])
            })
コード例 #8
0
ファイル: test_cart_no_profile.py プロジェクト: ljean/balafon
    def test_post_cart_no_profile(self):
        """It should create a new sale and action"""

        store_item1 = mommy.make(models.StoreItem)
        store_item2 = mommy.make(models.StoreItem)

        delivery_point = mommy.make(models.DeliveryPoint)

        zone_type = ZoneType.objects.get_or_create(type="country")[0]
        default_country = get_default_country()
        country = Zone.objects.get_or_create(name=default_country, type=zone_type, parent=None)[0]

        contact_data = {
            'lastname': 'Dupond',
            'firstname': 'Paul',
            'email': '*****@*****.**',
            'address': '1 rue la ré',
            'city': 'Lyon',
            'zip_code': '69000',
            'country': country.id,
        }

        data = {
            'items': [
                {'id': store_item1.id, 'quantity': 2},
                {'id': store_item2.id, 'quantity': 1},
            ],
            'delivery_point': delivery_point.id,
            'purchase_datetime': datetime(2015, 7, 23, 12, 0),
            'contact': contact_data,
        }

        url = reverse('store_post_cart_no_profile')

        response = self.client.post(url, data, format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

        self.assertEqual(response.data['ok'], True)
        self.assertEqual(len(response.data['warnings']), 0)
        self.assertEqual(response.data['deliveryDate'], data['purchase_datetime'])
        self.assertEqual(response.data['deliveryPlace'], delivery_point.name)

        action_type = ActionType.objects.get(name=get_cart_type_name())

        action_queryset = Action.objects.filter(type=action_type)
        self.assertEqual(action_queryset.count(), 1)
        action = action_queryset[0]

        self.assertEqual(response.data['action'], action.id)

        self.assertEqual(action.contacts.count(), 1)
        contact = action.contacts.all()[0]
        self.assertEqual(contact.lastname, contact_data['lastname'])
        self.assertEqual(contact.firstname, contact_data['firstname'])
        self.assertEqual(contact.email, contact_data['email'])
        self.assertEqual(contact.address, contact_data['address'])
        self.assertEqual(contact.city.name, contact_data['city'])
        self.assertEqual(contact.zip_code, contact_data['zip_code'])
        self.assertEqual(contact.get_country(), country)

        self.assertEqual(action.subject, '')
        self.assertEqual(action.detail, '')
        self.assertEqual(action.planned_date, data['purchase_datetime'])
        self.assertEqual(action.sale.payment_mode, None)
        self.assertEqual(action.sale.analysis_code, models.SaleAnalysisCode.objects.get(name='Internet'))

        self.assertEqual(action.sale.saleitem_set.count(), 2)
        self.assertEqual(action.sale.saleitem_set.all()[0].item, store_item1)
        self.assertEqual(action.sale.saleitem_set.all()[0].text, store_item1.name)
        self.assertEqual(action.sale.saleitem_set.all()[0].unit_price(), store_item1.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[0].vat_rate, store_item1.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[0].quantity, 2)

        self.assertEqual(action.sale.saleitem_set.all()[1].item, store_item2)
        self.assertEqual(action.sale.saleitem_set.all()[1].text, store_item2.name)
        self.assertEqual(action.sale.saleitem_set.all()[1].unit_price(), store_item2.pre_tax_price)
        self.assertEqual(action.sale.saleitem_set.all()[1].vat_rate, store_item2.vat_rate)
        self.assertEqual(action.sale.saleitem_set.all()[1].quantity, 1)

        self.assertEqual(len(mail.outbox), 2)
        self.assertEqual(mail.outbox[0].to, [contact.email])
        self.assertEqual(mail.outbox[1].to, [settings.BALAFON_NOTIFICATION_EMAIL])

        store_item1 = models.StoreItem.objects.get(id=store_item1.id)
        self.assertEqual(store_item1.stock_count, None)

        store_item2 = models.StoreItem.objects.get(id=store_item2.id)
        self.assertEqual(store_item2.stock_count, None)