Appearance
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.
| Covers | How every amount on a booking is worked out |
| Checked against | ems-apis/financial/, dev environment |
| Date checked | 5 August 2026 |
| Owner | engineering 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
| Piece | What it is |
|---|---|
| Rate | What the vendor charges for the experience. |
| Add-ons | Extras, each with its own price and quantity. |
| Promotion | A discount, if one applies. |
| Grand total | What the guest pays. Tax is inside this number. |
| Tax | The portion of the grand total that is tax. |
| Platform fee | What Delta takes. Called the service fee or app fee in the code. |
| Commission | What a partner takes, when one is involved. |
| Net income | What 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 total | Tax shown | Formula gives |
|---|---|---|
| ¥50,000 | ¥5,752 | 5,752.21 |
| ¥21,800 | ¥2,507 | 2,507.96 |
| IDR 14,001 | IDR 1,611 | 1,610.73 |
Confirmed in code. ems-apis/financial/former_calculation.go:70-80
Platform fee
platform_fee = amount × (1 + fee_rate/100) − amountWhich is the same as amount × fee_rate/100, written the long way round.
Default rate: 3.6%. Confirmed in code — ems-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/100Default commission: 0%. Confirmed in code — ems-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
- Apply the discount, if commission is being used as a discount
- Platform fee
- Commission
- 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_limitThe 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/100Careful. 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 code —
ems-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 code —
ems-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 code —
ems-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 code —
ems-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 code —
ems-apis/financial/former_calculation.go:82-98againstems-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 code —
ems-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 code —
ems-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 code —
ems-apis/financial/financial.go:127-136, 5 Aug 2026.
What is not established yet
| Gap | Why it matters | Who can settle it |
|---|---|---|
| Where the tax rate is actually set, and whether it varies by vendor or by experience | Every 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 kept | The whole refund conversation depends on it | engineering + product |
| Instalments and deposits | A booking can have several payments due at different times; none of that is documented here | engineering |
| What the payment provider charges, and who absorbs it | Not visible in these formulas at all | engineering + finance |
| Whether the older calculation path is still in use | The code marks several fields as "will be deprecated" but they are still there | engineering |
| Which of these numbers appear on the invoice PDF, and under what names | Finance reconciles against that document | engineering |