Suites · hospitality
Hospitality: restaurants, cafes, bars and hotels
Front of house and kitchen for food service and hotels: bills and service charge, splitting the bill, tips, menu costing and allergens, room rates and occupancy.
58 capabilities (30 core, 28 optional) and 15 gaps, in build order. Put each line in the file that calls it, then fune build.
Allergen information is safety-critical: hospitality.allergen-matrix only reports what the ingredient data declares. Keep that data current and have staff confirm allergens with the customer.
UK first: the 14 allergens, VAT on hospitality and tourist levies follow UK rules.
Calculates tax from published rules; it is not tax advice. Have an accountant check how the app uses it before anyone files a return.
TypeScript Python Rust
1. Bills and payment
Total a table's bill, add service and split it between diners to the penny.
hospitality.service-charge core
Adds a discretionary service charge to the bill's eligible lines at a basis-point rate.
A discretionary service charge on a bill's eligible lines, as a basis-point rate with explicit rounding.
from fune.hospitality.service_charge import service_charge # hospitality.service-charge@^1
1.0.0
hospitality.bill-split core
Splits a bill evenly, by item or by share, exactly, sharing the service charge in proportion.
Split a restaurant bill evenly, by item or by share, exactly to the penny, with the service charge shared in proportion.
from fune.hospitality.bill_split import bill_split # hospitality.bill-split@^1
1.0.0
order-taking Taking orders at the table or counter, sending them to the kitchen (KDS or printer) and tracking their status.card-payments Taking card payments through a terminal or payment provider and reconciling them to bills.
2. Tips and tronc
Share the tips pool fairly between staff.
hospitality.tronc-allocation core
Shares a tips pool by hours, points, or hours times points, exactly to the penny.
Share a tips pool (tronc) between staff by hours worked, points, or hours times points, exactly to the penny.
from fune.hospitality.tronc_allocation import tronc_allocation # hospitality.tronc-allocation@^1
1.0.0
staff-rota Staff rotas and clocking in and out, which produce the hours the tronc is shared by.
4. Bookings and cancellations
Take bookings and charge fairly when guests cancel late.
hospitality.cancellation-charge core
Cancellation fee for a booking from a policy of notice bands and the notice given.
Cancellation fee for a booking from a policy of notice bands and the days of notice given.
from fune.hospitality.cancellation_charge import cancellation_charge # hospitality.cancellation-charge@^1
1.0.0
table-availability Table plans and availability: which tables are free for a party size at a time, holding and confirming reservations.booking-notifications Confirmation and reminder emails or texts to guests.
5. Rooms (hotels)
Price stays and report on how the rooms are selling.
hospitality.room-rate core
Prices a stay night by night from a seasonal, day-of-week rate table, less length-of-stay discounts.
Price a hotel stay night by night from the caller's seasonal, day-of-week rate table, less any length-of-stay discount.
from fune.hospitality.room_rate import room_rate # hospitality.room-rate@^1
1.0.0
hospitality.occupancy-adr-revpar optional
Occupancy, average daily rate and RevPAR for a period.
Hotel occupancy, average daily rate (ADR) and revenue per available room (RevPAR) for a period.
from fune.hospitality.occupancy_adr_revpar import occupancy_adr_revpar # hospitality.occupancy-adr-revpar@^1
1.0.0
hospitality.tourist-tax optional
Visitor levy on an overnight stay: Edinburgh's 5%, Cardiff's per person per night, or your own rule.
Visitor levy (tourist tax) on an overnight stay: Edinburgh's 5%, Cardiff's per person per night, or a caller's own rule.
from fune.hospitality.tourist_tax import tourist_tax # hospitality.tourist-tax@^1
1.0.1
room-inventory Room availability, allocation and overbooking across dates and channels (channel managers, OTAs).
Hold money as currency-tagged integer minor units and do plain arithmetic on it safely.
money.amount core
The Money type ({ minor, currency }) every other money capability takes and returns.
A currency-tagged monetary amount held in integer minor units.
from fune.money.amount import money # money.amount@^1
1.0.2
money.add core
Adds and subtracts amounts, refusing to mix currencies by accident.
Add, subtract and negate monetary amounts, refusing to mix currencies.
from fune.money.add import add_money # money.add@^1
1.0.1
money.sum core
Totals a list of amounts, with an explicit currency for an empty list.
Total a list of monetary amounts, with an explicit currency for the empty case.
from fune.money.sum import sum_money # money.sum@^1
1.0.1
money.compare core
Compares, mins, maxes and clamps amounts of one currency without unwrapping them.
Compare two amounts of one currency, refusing to compare across currencies; min, max and clamp too.
from fune.money.compare import compare_money, min_money, max_money, clamp_money # money.compare@^2
2.0.04 functions
7. Rates and rounding from money-basics
Apply percentages and divide amounts with the rounding stated, never a float.
money.apply-rate core
Applies a basis-point rate (VAT, discount, commission) to an amount with explicit rounding.
Apply a rate expressed in basis points to a monetary amount, with an explicit rounding mode.
from fune.money.apply_rate import apply_rate # money.apply-rate@^1
1.0.1
math.round-div core
Integer division with a named rounding mode, for any money maths the others do not cover.
Integer division with an explicit rounding mode, for money arithmetic that must not drift.
from fune.math.round_div import round_div # math.round-div@^1
1.0.0
math.basis-points optional
Converts "12.5%" to and from basis points exactly, for rates typed in by users.
Convert a rate between percent, basis points and a plain ratio exactly, as decimal text or integer basis points.
from fune.math.basis_points import convert_rate, to_basis_points, from_basis_points # math.basis-points@^2
2.0.03 functions
math.percent-change optional
Percentage change between two figures in basis points, for "up 4.2% on last month".
Percentage change from one value to another, in basis points, with an explicit rounding mode.
from fune.math.percent_change import percent_change # math.percent-change@^1
1.0.0
math.rational optional
Exact fractions for rates that must not drift across many steps.
Exact fraction arithmetic, always reduced, for rates and ratios that must not drift.
from fune.math.rational import calculate_rational, rational, add_rational, subtract_rational, multiply_rational, divide_rational, compare_rational, rational_to_integer # math.rational@^2
2.0.08 functions
math.round-div-big optional
Rounded division on numbers past 2^53, for very large totals.
Divide two integers of any size with an explicit rounding mode, on decimal strings, for exact money sums past 2^53.
from fune.math.round_div_big import round_div_big # math.round-div-big@^1
1.0.0
Divide an amount between people, periods or lines so the parts add back to the whole.
money.allocate core
Splits an amount by ratios (60/40, by quantity) without losing or inventing a penny.
Split an amount across ratios without losing or inventing a single minor unit.
from fune.money.allocate import allocate # money.allocate@^1
1.0.1
money.split-even optional
Splits an amount into n near-equal parts that sum exactly, for instalments or shares.
Split an amount into n near-equal parts that add back up to exactly the whole.
from fune.money.split_even import split_even # money.split-even@^1
1.0.0
9. Display and input from money-basics
Show amounts to people and read what they type.
money.format core
Renders an amount as text with the currency's real number of decimal places.
Render a monetary amount as text, using the currency's real minor-unit precision.
from fune.money.format import format_money # money.format@^1
1.0.0
money.parse optional
Reads "£1,234.50" or "1.234,50 €" typed by a user into minor units, strictly.
Parse "£1,234.50" or "1.234,50 €" into integer minor units, strictly: no guessing, no rounding.
from fune.money.parse import parse_money # money.parse@^1
1.0.0
money.currency-digits optional
How many decimal places each ISO 4217 currency has, for input boxes and validation.
How many decimal places a currency's minor unit has, from the ISO 4217 list.
from fune.money.currency_digits import currency_digits # money.currency-digits@^1
1.0.0
10. Other currencies from money-basics
Convert between currencies at a rate you hold.
money.convert optional
Converts an amount at a supplied exact rate with explicit rounding.
Convert an amount to another currency at a supplied exact rate, with an explicit rounding mode.
from fune.money.convert import convert_money # money.convert@^1
1.0.0
11. Calendar arithmetic from dates-basics
Move and measure ISO dates exactly, with no date library and no clock reads.
dates.add-days core
Shifts a date by whole days, for due dates and windows.
Shift an ISO date by a whole number of days, forwards or backwards, with exact calendar arithmetic.
from fune.dates.add_days import add_days # dates.add-days@^1
1.0.0
dates.add-months core
Adds months clamping to month end, so 31 January plus a month is the end of February.
Add calendar months to an ISO date, clamping to the month end: 31 Jan + 1 month is 28 or 29 Feb.
from fune.dates.add_months import add_months # dates.add-months@^1
1.0.0
dates.days-between core
Signed calendar days between two dates, for ages of invoices and stays.
Calendar days from one ISO date to another, signed: negative when the second date is earlier.
from fune.dates.days_between import days_between # dates.days-between@^1
1.0.0
dates.month-boundaries core
First and last day of a date's month, for monthly periods and statements.
The first day, last day and length of the calendar month containing a date.
from fune.dates.month_boundaries import month_boundaries # dates.month-boundaries@^1
1.0.0
dates.day-of-week core
ISO weekday of a date, for weekend rules and opening hours.
The ISO 8601 day of the week for a date: 1 is Monday through 7 is Sunday.
from fune.dates.day_of_week import day_of_week # dates.day-of-week@^1
1.0.0
dates.is-leap-year optional
Whether a year is a leap year, for 365/366-day calculations.
Whether a year is a Gregorian leap year: every 4th, except centuries, except every 400th.
from fune.dates.is_leap_year import is_leap_year # dates.is-leap-year@^1
1.0.0
dates.overlap optional
Days two date ranges share, for prorating and clash checks.
Days two date ranges have in common, with the end of each range stated as inclusive or exclusive.
from fune.dates.overlap import overlap_days # dates.overlap@^1
1.0.0
dates.age optional
Age in whole years on a date, handling 29 February birthdays.
Age in whole years on a given date, with 29 February birthdays ageing on 1 March in other years.
from fune.dates.age import age # dates.age@^1
1.0.0
12. Periods and reporting dates from dates-basics
Put dates into the periods reports are grouped by.
dates.quarter core
Calendar and fiscal quarter of a date for any year-start month.
Calendar quarter and fiscal quarter of a date, with the fiscal year and quarter date ranges, for any start month.
from fune.dates.quarter import quarter # dates.quarter@^1
1.0.0
dates.week-number optional
ISO week number and week-year, for weekly reports.
ISO 8601 week number and week-numbering year of a date: weeks start Monday, week 1 holds the first Thursday.
from fune.dates.week_number import week_number # dates.week-number@^1
1.0.0
dates.day-count-fraction optional
Year fraction by ACT/365F, ACT/360, 30/360 or ACT/ACT, for interest periods.
Year fraction between two dates by ACT/365F, ACT/360, 30/360, 30E/360 or ACT/ACT ISDA, as an exact fraction.
from fune.dates.day_count_fraction import day_count_fraction # dates.day-count-fraction@^1
1.0.0
13. Working days and holidays from dates-basics
Skip weekends and public holidays when counting or adding days.
dates.bank-holidays core
UK bank holidays for a region and year, as gov.uk publishes them.
UK bank and public holidays for a region and year, as published by gov.uk, including one-off holidays.
from fune.dates.bank_holidays import bank_holidays # dates.bank-holidays@^1
1.0.1
dates.add-business-days core
Moves a date by working days, skipping weekends and a holiday list.
Move a date forward or back by working days, skipping weekends and a caller-supplied holiday list.
from fune.dates.add_business_days import add_business_days # dates.add-business-days@^1
1.0.0
dates.business-days-between core
Working days between two dates, for SLAs and notice periods.
Working days between two dates, excluding weekends and a caller-supplied holiday list.
from fune.dates.business_days_between import business_days_between # dates.business-days-between@^1
1.0.0
14. Repeating schedules from dates-basics
Generate the dates of something that repeats.
dates.recurrence optional
The next n dates of a rule: monthly on the 31st, last Friday, every two weeks.
The next n dates of a repeating rule: monthly on a day, last weekday of the month, every k days or weeks, yearly.
from fune.dates.recurrence import recurrence # dates.recurrence@^1
1.0.0
15. Times and durations from dates-basics
Work with times of day, durations and timestamps.
time.duration optional
Parses and adds durations like 1h30m in whole minutes, and formats the total.
Parse durations written as 1h30m, 90m or 01:30, add them up in whole minutes, and format the total.
from fune.time.duration import duration # time.duration@^1
1.0.0
time.minutes-between optional
Minutes between two local date-times, across midnight.
Minutes from one local date and time to another, correct across midnight; wall-clock time, no time zones.
from fune.time.minutes_between import minutes_between # time.minutes-between@^1
1.0.0
time.round-to-increment optional
Rounds minutes to a billing increment such as 6 or 15.
Round a duration in minutes to a billing increment such as 6 or 15 minutes, up, down or to nearest.
from fune.time.round_to_increment import round_to_increment # time.round-to-increment@^1
1.0.0
time.iso-to-unix optional
RFC 3339 timestamps to Unix seconds.
An RFC 3339 timestamp with a Z or offset, such as 2026-09-26T13:00:00+01:00, to Unix time in whole seconds.
from fune.time.iso_to_unix import iso_to_unix # time.iso-to-unix@^1
1.0.0
time.unix-to-iso optional
Unix seconds to an ISO 8601 UTC timestamp.
Unix time in seconds to an ISO 8601 UTC timestamp such as 2026-09-26T12:00:00Z, for years 0001 to 9999.
from fune.time.unix_to_iso import unix_to_iso # time.unix-to-iso@^1
1.0.0
time.countdown optional
Seconds left until a moment and a 4:05 style timer text.
Seconds left until a Unix time, whether it has passed, and a timer text like 4:05, for tokens or retry waits.
from fune.time.countdown import countdown # time.countdown@^1
1.0.0
16. VAT from uk-tax
Work out VAT from the dated rates HMRC publishes.
finance.tax.vat-rate core Unreviewed
The VAT rate in force for a jurisdiction, category and date; the others look it up.
Look up the VAT rate in force for a jurisdiction, category and date.
from fune.finance.tax.vat_rate import vat_rate # finance.tax.vat-rate@^1
1.2.2
finance.tax.add-vat core Unreviewed
Net to gross: VAT on a net amount at the rate on the date of supply.
Add VAT to a net amount using the rate in force on the date of supply.
from fune.finance.tax.add_vat import add_vat # finance.tax.add-vat@^1
1.0.1
finance.tax.remove-vat core Unreviewed
Gross to net: the VAT already inside a VAT-inclusive price.
Extract the VAT already included in a gross amount, using the rate in force on the date of supply.
from fune.finance.tax.remove_vat import remove_vat # finance.tax.remove-vat@^1
1.0.2
finance.tax.vat-return optional Unreviewed
The nine-box VAT return totals for a period from categorised sales and purchases.
UK nine-box VAT return totals for a period from categorised sales and purchases (VAT Notice 700/12).
from fune.finance.tax.vat_return import vat_return # finance.tax.vat-return@^1
1.0.1
finance.tax.vat-flat-rate optional Unreviewed
VAT due under the Flat Rate Scheme by business sector, for small businesses on it.
UK VAT Flat Rate Scheme: VAT due on gross turnover at the sector's dated rate, limited cost rate and first-year 1% off.
from fune.finance.tax.vat_flat_rate import flat_rate_vat # finance.tax.vat-flat-rate@^1
1.0.1
17. Tax periods from uk-tax
Put dates into the UK periods tax is worked out over.
dates.uk-tax-year core
Which UK tax year (6 April to 5 April) a date falls in.
The UK personal tax year containing a date: 6 April to 5 April, with HMRC's label.
from fune.dates.uk_tax_year import uk_tax_year # dates.uk-tax-year@^1
1.0.0
18. Tax identifiers from uk-tax
Check the numbers HMRC and Companies House issue before storing them.
validation.uk-vat-number core
Checks a UK VAT registration number's checksum.
Check a UK VAT registration number against HMRC's mod-97 checksum, including the post-2010 9755 variant.
from fune.validation.uk_vat_number import is_uk_vat_number # validation.uk-vat-number@^1
1.0.0
validation.uk-utr optional
Checks a Unique Taxpayer Reference's check digit.
Check an HMRC Unique Taxpayer Reference's modulus 11 check digit, accepting the K and spacing people type.
from fune.validation.uk_utr import validate_uk_utr # validation.uk-utr@^2
2.0.1
validation.uk-company-number optional
Checks and pads a Companies House company number.
Check a Companies House company number's format and prefix (SC, NI, OC, LP...) and zero-pad it to eight characters.
from fune.validation.uk_company_number import validate_uk_company_number # validation.uk-company-number@^2
2.0.1
Gaps What this kind of app usually needs that Functional Weave does not have yet: write these yourself, or use a service.
fx-rate-source Where exchange rates come from: money.convert takes a rate you supply; fetching and storing daily rates (ECB, a provider's API) is yours.money-storage Storing amounts: the database columns (integer minor units plus a currency code) and their migrations are yours.time-zones Time zones and daylight saving: caps works in ISO dates, UTC and wall-clock times; converting with the IANA tz rules is yours.locale-formatting Showing dates in a user's language and format ("3 octobre 2026"): caps returns ISO dates, not localised text.non-uk-holidays Public holidays outside the UK: dates.bank-holidays is UK only; pass another country's list to the working-day functions yourself.mtd-submission Making Tax Digital: submitting the return to HMRC's VAT API (OAuth, fraud-prevention headers, obligations) is yours; caps gives the nine boxes.corporation-tax Corporation tax and self-assessment income tax computations are not in caps.vat-number-lookup Checking that a VAT number is registered (HMRC's lookup API) is network work; caps checks the checksum only.