Esempio n. 1
0
    def get_orderability_errors(  # noqa (C901)
            self, supplier, quantity, customer, ignore_minimum=False):
        """
        Yield ValidationErrors that would cause this product to not be orderable.

        :param supplier: Supplier to order this product from. May be None.
        :type supplier: shoop.core.models.suppliers.Supplier
        :param quantity: Quantity to order.
        :type quantity: int|Decimal
        :param customer: Customer contact.
        :type customer: shoop.core.models.Contact
        :param ignore_minimum: Ignore any limitations caused by quantity minimums.
        :type ignore_minimum: bool
        :return: Iterable[ValidationError]
        """
        for error in self.get_visibility_errors(customer):
            yield error

        if supplier is None and not self.suppliers.exists():
            # `ShopProduct` must have at least one `Supplier`.
            # If supplier is not given and the `ShopProduct` itself
            # doesn't have suppliers we cannot sell this product.
            yield ValidationError(
                _('The product has no supplier.'),
                code="no_supplier"
            )

        if not ignore_minimum and quantity < self.minimum_purchase_quantity:
            yield ValidationError(
                _('The purchase quantity needs to be at least %d for this product.') % self.minimum_purchase_quantity,
                code="purchase_quantity_not_met"
            )

        if supplier and not self.suppliers.filter(pk=supplier.pk).exists():
            yield ValidationError(
                _('The product is not supplied by %s.') % supplier,
                code="invalid_supplier"
            )

        if self.product.is_package_parent():
            for child_product, child_quantity in six.iteritems(self.product.get_package_child_to_quantity_map()):
                child_shop_product = child_product.get_shop_instance(shop=self.shop)
                if not child_shop_product:
                    yield ValidationError("%s: Not available in %s" % (child_product, self.shop), code="invalid_shop")
                for error in child_shop_product.get_orderability_errors(
                        supplier=supplier,
                        quantity=(quantity * child_quantity),
                        customer=customer,
                        ignore_minimum=ignore_minimum
                ):
                    code = getattr(error, "code", None)
                    yield ValidationError("%s: %s" % (child_product, error), code=code)

        if supplier and self.product.stock_behavior == StockBehavior.STOCKED:
            for error in supplier.get_orderability_errors(self, quantity, customer=customer):
                yield error

        purchase_multiple = self.purchase_multiple
        if quantity > 0 and purchase_multiple > 1 and (quantity % purchase_multiple) != 0:
            p = (quantity // purchase_multiple)
            smaller_p = max(purchase_multiple, p * purchase_multiple)
            larger_p = max(purchase_multiple, (p + 1) * purchase_multiple)
            if larger_p == smaller_p:
                message = _('The product can only be ordered in multiples of %(package_size)s, '
                            'for example %(smaller_p)s %(unit)s.') % {
                    "package_size": purchase_multiple,
                    "smaller_p": smaller_p,
                    "unit": self.product.sales_unit,
                }
            else:
                message = _('The product can only be ordered in multiples of %(package_size)s, '
                            'for example %(smaller_p)s or %(larger_p)s %(unit)s.') % {
                    "package_size": purchase_multiple,
                    "smaller_p": smaller_p,
                    "larger_p": larger_p,
                    "unit": self.product.sales_unit,
                }
            yield ValidationError(message, code="invalid_purchase_multiple")

        for receiver, response in get_orderability_errors.send(
            ShopProduct, shop_product=self, customer=customer, supplier=supplier, quantity=quantity
        ):
            for error in response:
                yield error
Esempio n. 2
0
    def get_orderability_errors(  # noqa (C901)
            self,
            supplier,
            quantity,
            customer,
            ignore_minimum=False):
        """
        Yield ValidationErrors that would cause this product to not be orderable.

        :param supplier: Supplier to order this product from. May be None.
        :type supplier: shoop.core.models.suppliers.Supplier
        :param quantity: Quantity to order.
        :type quantity: int|Decimal
        :param customer: Customer contact.
        :type customer: shoop.core.models.Contact
        :param ignore_minimum: Ignore any limitations caused by quantity minimums.
        :type ignore_minimum: bool
        :return: Iterable[ValidationError]
        """
        for error in self.get_visibility_errors(customer):
            yield error

        if supplier is None and not self.suppliers.exists():
            # `ShopProduct` must have at least one `Supplier`.
            # If supplier is not given and the `ShopProduct` itself
            # doesn't have suppliers we cannot sell this product.
            yield ValidationError(_('The product has no supplier.'),
                                  code="no_supplier")

        if not ignore_minimum and quantity < self.minimum_purchase_quantity:
            yield ValidationError(_(
                'The purchase quantity needs to be at least %d for this product.'
            ) % self.minimum_purchase_quantity,
                                  code="purchase_quantity_not_met")

        if supplier and not self.suppliers.filter(pk=supplier.pk).exists():
            yield ValidationError(_('The product is not supplied by %s.') %
                                  supplier,
                                  code="invalid_supplier")

        if self.product.is_package_parent():
            for child_product, child_quantity in six.iteritems(
                    self.product.get_package_child_to_quantity_map()):
                child_shop_product = child_product.get_shop_instance(
                    shop=self.shop)
                if not child_shop_product:
                    yield ValidationError("%s: Not available in %s" %
                                          (child_product, self.shop),
                                          code="invalid_shop")
                for error in child_shop_product.get_orderability_errors(
                        supplier=supplier,
                        quantity=(quantity * child_quantity),
                        customer=customer,
                        ignore_minimum=ignore_minimum):
                    code = getattr(error, "code", None)
                    yield ValidationError("%s: %s" % (child_product, error),
                                          code=code)

        if supplier and self.product.stock_behavior == StockBehavior.STOCKED:
            for error in supplier.get_orderability_errors(self,
                                                          quantity,
                                                          customer=customer):
                yield error

        purchase_multiple = self.purchase_multiple
        if quantity > 0 and purchase_multiple > 1 and (quantity %
                                                       purchase_multiple) != 0:
            p = (quantity // purchase_multiple)
            smaller_p = max(purchase_multiple, p * purchase_multiple)
            larger_p = max(purchase_multiple, (p + 1) * purchase_multiple)
            if larger_p == smaller_p:
                message = _(
                    'The product can only be ordered in multiples of %(package_size)s, '
                    'for example %(smaller_p)s %(unit)s.') % {
                        "package_size": purchase_multiple,
                        "smaller_p": smaller_p,
                        "unit": self.product.sales_unit,
                    }
            else:
                message = _(
                    'The product can only be ordered in multiples of %(package_size)s, '
                    'for example %(smaller_p)s or %(larger_p)s %(unit)s.') % {
                        "package_size": purchase_multiple,
                        "smaller_p": smaller_p,
                        "larger_p": larger_p,
                        "unit": self.product.sales_unit,
                    }
            yield ValidationError(message, code="invalid_purchase_multiple")

        for receiver, response in get_orderability_errors.send(
                ShopProduct,
                shop_product=self,
                customer=customer,
                supplier=supplier,
                quantity=quantity):
            for error in response:
                yield error