Skip to content

Prices and fees

Page summary: Understand how EMS turns a selling price into tax, fees, commission, and vendor income.

Use this when: Use this when a number looks wrong, when defining partner commercial terms, or when testing calculations.

  • Tax is inside the displayed price.
  • Order of operations changes the result.
  • “From net” does not have one consistent meaning across all partner calculations.

Draft. The formulas are taken from the code and written out here exactly. The tax formula has been checked against real bookings in dev. The rest has not.

CoversHow every amount on a booking is worked out
Checked againstems-apis/financial/, dev environment
Date checked5 August 2026
Ownerengineering for the formulas, product and finance for the intent

Start here: three things that surprise people

1. Tax is already inside the price. It is not added on top. EMS works backwards out of the total to find how much of it was tax. A ¥50,000 booking with 13% tax has ¥5,752 of tax inside it. The guest pays ¥50,000.

2. "Net" does not mean after tax. In EMS, net means after the platform fee. Commission "from net" is worked out on the amount left once the platform fee is taken off — tax is still in there. Anyone assuming net means after tax will get a different number.

3. The order is fixed and it changes the answer. Discount, then platform fee, then commission, then tax. Always that order. A percentage applied at a different point gives a different result.


The pieces

PieceWhat it is
RateWhat the vendor charges for the experience.
Add-onsExtras, each with its own price and quantity.
PromotionA discount, if one applies.
Grand totalWhat the guest pays. Tax is inside this number.
TaxThe portion of the grand total that is tax.
Platform feeWhat Delta takes. Called the service fee or app fee in the code.
CommissionWhat a partner takes, when one is involved.
Net incomeWhat is left for the vendor.

The formulas

Written exactly as the code has them.

Tax

tax = amount − amount ÷ (1 + tax_rate/100)

Tax comes out of the price, never on top.

Confirmed in dev, 5 August 2026, against three real bookings at 13%:

Grand totalTax shownFormula gives
¥50,000¥5,7525,752.21
¥21,800¥2,5072,507.96
IDR 14,001IDR 1,6111,610.73

Confirmed in code. ems-apis/financial/former_calculation.go:70-80

Platform fee

platform_fee = amount × (1 + fee_rate/100) − amount

Which is the same as amount × fee_rate/100, written the long way round.

Default rate: 3.6%. Confirmed in codeems-apis/constants/vendor_policy.go:42.

Confirmed in code. ems-apis/financial/former_calculation.go:100-113, ems-apis/financial/helper.go:14-27

Commission

Two ways, chosen per partnership.

from gross:  commission = original_amount × commission_rate/100
from net:    commission = (amount − platform_fee) × commission_rate/100

Default commission: 0%. Confirmed in codeems-apis/constants/vendor_default_value.type.go:5.

Confirmed in code. ems-apis/financial/former_calculation.go:82-98

Net income — what the vendor keeps

net_income = | amount − tax − platform_fee − commission |

Note the bars. The result is forced positive. See negative vendor income is turned positive (PRC-004).

Confirmed in code. ems-apis/financial/former_calculation.go:155

The order

  1. Apply the discount, if commission is being used as a discount
  2. Platform fee
  3. Commission
  4. Tax

Fixed. Not configurable.

Confirmed in code. ems-apis/financial/former_calculation.go:114-131


Partner selling

A partner deal uses one of two models, and they work differently enough that mixing them up produces wrong money.

White label — the partner sets their own price

The vendor sets a floor. The partner sells above it and keeps the difference.

bottom_limit        = rate − (rate × bottom_limit_percentage/100)
platform_fee        = sell_price × platform_fee_rate/100
tax                 = sell_price − sell_price ÷ (1 + tax_rate/100)
partner_commission  = sell_price − bottom_limit

The partner's earnings are whatever they price above the floor. A sell price below the floor is rejected as invalid.

Authorised agent — the partner takes a percentage

The vendor's rate is the price. The partner takes an agreed cut.

platform_fee          = rate × platform_fee_rate/100
tax                   = rate − rate ÷ (1 + tax_rate/100)
commission_from_gross = rate × commission_rate/100
commission_from_net   = (rate − tax) × commission_rate/100

Careful. In this model "from net" means after tax. In the ordinary calculation above, "from net" means after the platform fee. The same words, two different meanings, in the same system. See "Net" means two different things (PRC-005).

Confirmed in code. ems-apis/financial/financial.go:60-95, 108-125


Money and currencies

Amounts are whole numbers, not decimals. How many decimal places a currency has is recorded per currency — yen and won have none, most others have two.

Rounding uses one shared helper that adds 0.5 and cuts off the rest. That is rounding to nearest, half up. It is named as though it rounds up, which it does not, and it is wrong for negative amounts.

Confirmed in code. ems-apis/financial/currency.go:9-95, ems-apis/financial/helper.go:5-7


Rules

Tax is inside the price PRC-001

What happens today: Tax is worked backwards out of the total. The guest pays the displayed amount; part of it was tax.

When it applies: Every booking.

Applies to: Everyone. The rate is set per vendor.

Expected behaviour: Exactly this.

Evidence and test details
  • Checked Confirmed in dev — three bookings at 13%, 5 Aug 2026. Confirmed in codeems-apis/financial/former_calculation.go:70-80.

The order of operations is fixed PRC-002

What happens today: Discount, platform fee, commission, tax. Always.

When it applies: Every calculation.

Applies to: Everyone. Not configurable.

Expected behaviour: Not established. It has never been written down, so nobody has agreed it.

Why it matters: Change the order and every number changes. Any conversation about "should commission come before or after the fee" is already answered — it comes after.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/former_calculation.go:114-131, 5 Aug 2026.

Using commission as a discount does not do what it looks like PRC-003

What happens today: There is a setting to treat commission as a discount instead. When it is on, the code tries to force the calculation to "from gross" — but it changes the setting after the calculation has already copied it. The change never reaches the calculation, so the original setting is used.

When it applies: Any booking with commission-as-discount switched on and commission set to "from net".

Applies to: One partnership.

Expected behaviour: Presumably to force from gross, since that is plainly the intent of the line.

Status: No. The line has no effect.

Why it matters: It is a money difference on partner bookings, silently.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/former_calculation.go:139-152; the copy happens at line 140, the override at line 150, 5 Aug 2026.

Negative vendor income is turned positive PRC-004

What happens today: The vendor's net income is wrapped in an absolute value, so a negative result comes out positive.

When it applies: Whenever tax plus platform fee plus commission exceed the amount.

Applies to: Everyone.

Expected behaviour: Not established. A negative here means something is wrong with the deal, and hiding it means nobody finds out.

Why it matters: A misconfigured partnership that should show a loss will show a plausible-looking profit instead.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/former_calculation.go:155, 5 Aug 2026.

"Net" means two different things PRC-005

What happens today: In the ordinary calculation, commission "from net" means after the platform fee, with tax still included. In the partner calculation, "from net" means after tax. Same words, same system, different money.

When it applies: Any partner deal set to "from net".

Applies to: One partnership.

Expected behaviour: One meaning, or two different words.

Why it matters: Whoever agrees a commission rate with a partner is agreeing to one of two different numbers, and the contract will not say which.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/former_calculation.go:82-98 against ems-apis/financial/financial.go:75-79, 5 Aug 2026.

The rounding switch does nothing PRC-006

What happens today: Two fee helpers take a setting for whether to round. Both branches do exactly the same thing. The setting has no effect.

When it applies: Wherever those helpers are used.

Applies to: Everyone.

Expected behaviour: Either round differently, or drop the setting.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/helper.go:14-27, 5 Aug 2026.

Rounding is not what it is called PRC-007

What happens today: The shared rounding helper adds 0.5 and cuts off the rest, which rounds to the nearest whole number, half up. Its name says it rounds up. For negative amounts it gives the wrong answer.

When it applies: Every rounded amount.

Applies to: Everyone.

Expected behaviour: Not established. The behaviour may well be right; the name is not, and negative amounts are unhandled.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/helper.go:5-7, 5 Aug 2026.

A partner cannot sell below the floor PRC-008

What happens today: In a white label deal, a sell price below the vendor's floor is rejected. So is a zero or negative rate or sell price.

When it applies: Every white label calculation.

Applies to: One partnership.

Expected behaviour: Exactly this.

Evidence and test details
  • Checked Confirmed in codeems-apis/financial/financial.go:127-136, 5 Aug 2026.

What is not established yet

GapWhy it mattersWho can settle it
Where the tax rate is actually set, and whether it varies by vendor or by experienceEvery booking depends on it. The 13% seen in dev has not been traced to a setting.engineering
How refunds are worked out — what is refundable and what is keptThe whole refund conversation depends on itengineering + product
Instalments and depositsA booking can have several payments due at different times; none of that is documented hereengineering
What the payment provider charges, and who absorbs itNot visible in these formulas at allengineering + finance
Whether the older calculation path is still in useThe code marks several fields as "will be deprecated" but they are still thereengineering
Which of these numbers appear on the invoice PDF, and under what namesFinance reconciles against that documentengineering