Functional Weave
Code in TypeScript

hospitality.gross-profit-menu@1.0.0

impl/python/menu_price_for_gp.py

1,613 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 .finance_markup_price import markup_price  ← from finance.markup-price ^1.0.0 · built alongside by fune
from .finance_tax_add_vat import add_vat  ← from finance.tax.add-vat ^1.0.0 · built alongside by fune
from .hospitality_gross_profit_menu_menu_gross_profit import menu_gross_profit  ← menuGrossProfit, another function of this group · built into the same file, even by a slim install
from .hospitality_gross_profit_menu_types import MenuGrossProfit
from .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune
from .money_amount import Money, money  ← from money.amount ^1.0.0 · built alongside by fune


def menu_price_for_gp(
    cost: Money,
    target_gp_basis_points: int,
    price_step: int,
    jurisdiction: str,
    category: str,
    on_date: str,
) -> MenuGrossProfit:
    """The menu price that reaches a target GP.

    The net price is the smallest that makes the target on the VAT-exclusive
    price (finance.markup-price, rounded up), VAT goes on top, and the menu
    price is rounded up to the step a menu is printed in. Rounding only ever
    goes up, so the GP returned is never below the target.
    """
    t = target_gp_basis_points
    if isinstance(t, bool) or not isinstance(t, int) or t < 0 or t > 9999:
        raise ValueError("targetGpBasisPoints must be a whole number from 0 to 9999, received %s" % (t,))
    if isinstance(price_step, bool) or not isinstance(price_step, int) or price_step < 1:
        raise ValueError("priceStep must be at least 1, received %s" % (price_step,))
    if cost.minor < 0:
        raise ValueError("cost must not be negative, received %d" % (cost.minor,))
    net = markup_price(cost, t, "margin", "up")
    gross = add_vat(net, jurisdiction, category, on_date).gross
    menu_price = money(round_div(gross.minor, price_step, "up") * price_step, gross.currency)
    return menu_gross_profit(cost, menu_price, jurisdiction, category, on_date)