Skip to main content

Add tariff groups & fees

Each fee category for the port (harbour dues, pilotage, boatmen, waste…) is a tariff group. Inside each group you add one or more tariffs — the individual fee lines. This page walks through creating both.

Open the Tariff groups screen

Go to Sidebar → Admin → Cost Calculations → Tariff groups (route /invoicing-and-tariffs/tariff-groups/cost-calculation).

You need the Tariff admin permission (invoices.tariff_admin) to create or edit groups.

Step 1 — Create a tariff group

Click New and fill in the group details:

FieldWhat to enter
NameDescriptive name, e.g. Den Helder — Harbour dues
System codepcc_<port>_<category>, e.g. pcc_denhelder_havengeld
Currency codeEUR
Starts onFirst date the fees apply, e.g. 2026-01-01
Ends onLeave blank for open-ended
UI TemplateLabel shown as the result section header, e.g. Harbour dues
Tariff group typeInvoice calculation
Application areaRead-only — already set to cost calculation

Click Save. You are now on the tariff group details page.

Step 2 — Gate the group to your port

Every tariff group must have a port gate condition. Without it the group's tariffs apply to all ports, not just yours.

On the Business logic card, open the Conditions tab and click Add:

FieldValue
Logic typeCustom
Field typeConditionString
Source field$.__DefinitionSystemCode
String operatorEquals
ValuepccDenHelder (your port's System code — exactly as you set it on the object)

Click Save on the condition. Repeat this on every tariff group you create for this port.

Step 3 — Add the tariffs (fees)

From the tariff group details page, navigate to the group's tariff list and click Add tariff. The tariff form has a Details card and a Business logic card.

Common fields for every tariff:

FieldWhat to enter
NameFee name, e.g. Harbour dues — zeeschip Nieuwe Diep
Amount typeNumber
Tariff typeRegular
Currency codeEUR
System codeShort stable code
UI TemplateLabel shown on the result line — required, cannot be empty
Starts on / Ends onMatch the fee schedule validity period

The Amount source field controls which shape the fee takes. Choose Direct or Matrix and fill in the fields described in each shape below.


Shape A — a rate per unit

Use this when the fee is a fixed rate multiplied by a vessel attribute (e.g. €0.93 per GT).

Details card:

FieldValue
Amount sourceDirect
AmountThe rate, e.g. 0.93
UI Templatee.g. Port dues ({{$.ship.gt}} × 0.93) — put the template in backticks if you want it literal, or use the actual Handlebars syntax inside the field

Business logic — Calculations tab → Add:

FieldValue
Logic typeCustom
Field typeCalculationPricePerUnit
Source field$.ship.gt (or $.ship.loa, $.tugsInbound.numberOfTugs, etc.)
Calculation order0

This tells the engine to multiply the Amount by the value at that field path.

Business logic — Conditions tab (optional): if this rate only applies to certain ship types, add a ConditionArray (see Conditions reference below).

Den Helder example: harbour dues for zeeschepen at Nieuwe Diep — Amount 0.93, CalculationPricePerUnit source $.ship.gt.


Shape B — a bracket lookup

Use this when the fee depends on which band a value falls into (e.g. pilotage priced by draught bracket).

Details card:

FieldValue
Amount sourceMatrix
Amount0
Amount source templateThe Handlebars key that drives the lookup, e.g. {{pilotsOutbound.draft}}

Business logic — Conditions tab → Add a ConditionNumeric to guard against zero/empty input:

FieldValue
Field typeConditionNumeric
Source fieldpilotsOutbound.draft
Numeric operatorGreaterThan
Value0

Then fill the Tariff Matrix card (see Step 4).

Den Helder example: inbound pilotage — Amount source Matrix, Amount source template {{pilotsInbound.draft}}, 169 draught brackets in dm.


Shape C — a flat fee

Use this when the fee is a fixed amount, optionally only for certain vessel types or conditions.

Details card:

FieldValue
Amount sourceDirect
AmountThe fixed fee, e.g. 120

Business logic — Conditions tab: add conditions to restrict when the tariff fires (e.g. ConditionArray on $.podh.callPeriod with Keys day). Leave conditions empty if the fee always applies.

Do not add a CalculationPricePerUnit node — none is needed for a flat fee.

Den Helder example: boatmen daytime — Amount 120, ConditionArray on $.podh.callPeriod = ["day"].


Step 4 — Fill the tariff matrix (brackets)

The Tariff Matrix card appears only when Amount source = Matrix. It is not shown for Direct tariffs.

Each row is a bracket:

ColumnNotes
NameBracket label, e.g. 0–270 dm
System codeAuto-filled; editable
AmountRate for this bracket
FromLower bound (inclusive). The first bracket must start at 0.
ToUpper bound (exclusive). The last bracket should use a large number, e.g. 9999, to cover all values.
UI TemplateLabel for this bracket's result line

Brackets must be contiguous — the To of one row equals the From of the next. Gaps cause the lookup to return nothing.

Click Add at the bottom of the card to append a blank row. Fill each row and click Save.

Importing brackets from Excel

For large bracket tables (Den Helder pilotage has 169 rows), use the import:

  1. Make sure Amount source = Matrix is saved on the tariff — the Import Tariff Matrix button only appears in view mode (not edit mode).
  2. Click Import Tariff Matrix in the page header.
  3. In the modal, click Download example file first to get the correct column layout.
  4. Fill the example file with your brackets.
  5. Tick Replace existing tariff matrix if you want to overwrite any rows already there.
  6. Click Import.

Always start with Download example file — the column order in the template is the one the importer expects.


Conditions reference

Add conditions on the Conditions tab of the Business logic card (on the tariff, not the group — unless it is the port gate, which goes on the group).

Condition typeWhen to useKey fields
ConditionStringPort gate — match the port System codeSource field $.__DefinitionSystemCode, String operator Equals, Value = pccDenHelder
ConditionArrayMatch against a List field (ship type, area, call period…)Source field e.g. $.general.shipType, Array operator Any, Values = array of List Keys e.g. tanker_lng, bulkcarrier
ConditionNumericNumeric comparisons (draft > 0, GT between two values…)Numeric operator: Between / Equals / GreaterThan / SmallerThan
ConditionBooleanYes/no flag fieldsBoolean operator True or False
ConditionBoolean

The ConditionBoolean type (for fields like ispsApplicable) was not present in the reference data used to build this documentation. The UI form shows True / False operators, but verify the result against a live boolean condition before using it in production.

"Apply once per call" — line grouping

Some fees should fire only once per port call regardless of how many tariff lines match (for example a waste fee that should not double-count). This line grouping behaviour has no UI screen — it requires a configuration change by the SHIPM8 team. Contact support if a fee needs it.