Functional Weave
Code in TypeScript

inventory.stock-turnover@1.0.0

impl/python.py

1,607 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .inventory_stock_turnover_types import StockTurnover
from .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, assert_same_currency, money  ← from money.amount ^1.0.0 · built alongside by fune


def _not_negative(name: str, amount: Money) -> None:
    if amount.minor < 0:
        raise ValueError("%s must not be negative, received %d" % (name, amount.minor))


def stock_turnover(opening_stock: Money, closing_stock: Money, cost_of_sales: Money, period_days: int) -> StockTurnover:
    """Turns, days inventory outstanding and days of cover. Each is one exact
    division rounded half-up, then made a float, so every language agrees.
    """
    assert_same_currency(opening_stock, closing_stock)
    assert_same_currency(opening_stock, cost_of_sales)
    _not_negative("openingStock", opening_stock)
    _not_negative("closingStock", closing_stock)
    _not_negative("costOfSales", cost_of_sales)
    if isinstance(period_days, bool) or not isinstance(period_days, int) or period_days < 1:
        raise ValueError("periodDays must be a whole number of days, at least 1, received %r" % (period_days,))
    both = opening_stock.minor + closing_stock.minor
    cogs = cost_of_sales.minor
    return StockTurnover(
        average_stock=money(round_div(both, 2, "half-up"), opening_stock.currency),
        turns=None if both == 0 else round_div(cogs * 200, both, "half-up") / 100,
        days_inventory_outstanding=None
        if cogs == 0
        else round_div(both * period_days * 10, cogs * 2, "half-up") / 10,
        days_of_cover=None if cogs == 0 else round_div(closing_stock.minor * period_days * 10, cogs, "half-up") / 10,
    )