<commit_before>from typing import TYPE_CHECKING

from django.conf import settings
from django.db.models import Sum
from django.db.models.functions import Coalesce

from ..core.exceptions import InsufficientStock
from .models import Stock, StockQuerySet

if TYPE_CHECKING:
    from ..product.models import Product, ProductVariant


def _get_quantity_allocated(stocks: StockQuerySet) -> int:
    return stocks.aggregate(
        quantity_allocated=Coalesce(Sum("allocations__quantity_allocated"), 0)
    )["quantity_allocated"]


def _get_available_quantity(stocks: StockQuerySet) -> int:
    quantity_allocated = _get_quantity_allocated(stocks)
    total_quantity = stocks.aggregate(total_quantity=Coalesce(Sum("quantity"), 0))[
        "total_quantity"
    ]
    return max(total_quantity - quantity_allocated, 0)


def check_stock_quantity(variant: "ProductVariant", country_code: str, quantity: int):
    """Validate if there is stock available for given variant in given country.

    If so - returns None. If there is less stock then required rise InsufficientStock
    exception.
    """
    stocks = Stock.objects.get_variant_stocks_for_country(country_code, variant)
    if not stocks:
        raise InsufficientStock(variant)

    if variant.track_inventory and quantity > _get_available_quantity(stocks):
        raise InsufficientStock(variant)<commit_msg>Reduce the number of queries<commit_after>from typing import TYPE_CHECKING

from django.conf import settings
from django.db.models import Sum
from django.db.models.functions import Coalesce

from ..core.exceptions import InsufficientStock
from .models import Stock, StockQuerySet

if TYPE_CHECKING:
    from ..product.models import Product, ProductVariant


def _get_quantity_allocated(stocks: StockQuerySet) -> int:
    return stocks.aggregate(
        quantity_allocated=Coalesce(Sum("allocations__quantity_allocated"), 0)
    )["quantity_allocated"]


def _get_available_quantity(stocks: StockQuerySet) -> int:
    results = stocks.aggregate(
        total_quantity=Coalesce(Sum("quantity"), 0),
        quantity_allocated=Coalesce(Sum("allocations__quantity_allocated"), 0),
    )
    total_quantity = results["total_quantity"]
    quantity_allocated = results["quantity_allocated"]
    return max(total_quantity - quantity_allocated, 0)


def check_stock_quantity(variant: "ProductVariant", country_code: str, quantity: int):
    """Validate if there is stock available for given variant in given country.

    If so - returns None. If there is less stock then required rise InsufficientStock
    exception.
    """
    stocks = Stock.objects.get_variant_stocks_for_country(country_code, variant)
    if not stocks:
        raise InsufficientStock(variant)

    if variant.track_inventory and quantity > _get_available_quantity(stocks):
        raise InsufficientStock(variant)
{'fraction_non_alphanumeric': 0.07830056179775281, 'fraction_numerical': 0.0024578651685393258, 'mean_word_length': 4.767206477732794, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '500423', 'n_tokens_mistral': 835, 'n_tokens_neox': 783, 'n_words': 213}