Functional Weave
Code in Rust

hospitality.gross-profit-menu@1.0.0

README.md

2,202 bytes · view raw

# hospitality.gross-profit-menu

Two functions for pricing a menu:

- `menuGrossProfit(cost, menuPrice, ...)`: the GP of a dish at its menu
  price. The VAT-inclusive price is split into VAT and net with
  `finance.tax.remove-vat`, and the GP and food cost are worked out on the net
  price with `finance.margin`.
- `menuPriceForGp(cost, target, priceStep, ...)`: the lowest menu price that
  reaches a target GP, rounded up to a price step (50 for the next 50p), and
  the GP it actually makes.

They are a group because they are two directions of one calculation.
`menuPriceForGp` answers with `menuGrossProfit`'s breakdown of the price it
chose.

## GP is on the price without VAT

In UK hospitality, GP (gross profit percentage) is `(net price - cost) / net
price`, where the net price excludes VAT. The VAT is collected for HMRC, not
earned. A 14.50 dish costing 3.50 at 20% VAT has a net price of 12.08 and a GP
of 71.03%. Working on the menu price gives 75.86%, which overstates it by five
points. The food cost percentage is `10000 - gpBasisPoints`, so the two always
add up to exactly 100%.

## The VAT rate is looked up, not assumed

The VAT rate comes from `finance.tax.vat-rate` for the jurisdiction, category
and date of sale. Food eaten on the premises is `HOSPITALITY` (20% in the UK
since April 2022, 5% and then 12.5% during the pandemic relief of 2020 to
2022). Cold takeaway food is usually `ZERO`. Which category a dish falls in
under VAT Notice 709/1 is the caller's decision.

## Pricing for a target

1. The net price is the smallest that reaches the target on the net
   (`finance.markup-price` with basis `margin`, rounded up).
2. VAT is added with `finance.tax.add-vat`.
3. The menu price is rounded **up** to a multiple of `priceStep`.

Every rounding step goes up, so the GP returned is never below the target. It
is usually a little above it, and the result shows by how much. A common
mistake is `cost / (1 - target)` on the menu price: 3.50 / 0.3 = 11.67 on the
menu is only a 64% GP once VAT is taken out.

## Errors

A negative cost or price, cost and price in different currencies, a target
outside 0 to 9999, a step below 1, or no VAT rule for the category and date.