Appearance
Vanhoutte Onboarding Flow (Reseller)
Overview
This is the onboarding flow for a reseller (Partner Admin) setting up one of their merchants on Vanhoutte POS. Vanhoutte is a Kassanet-family in-house POS, the twin of Hendrickx; the two share the same backend engine and differ only by provider identifier. The connection lives at route /vanhoutte.
Vanhoutte is location-specific: each location connects separately with its own credentials. Menu data is pulled one-way from the POS (Vanhoutte to Upvendo); items cannot be created in Upvendo. Orders are forwarded to the POS after payment is confirmed (Viva Wallet for Kiosk, Stripe for Online Ordering).
For the full integration mechanics (sync jobs, order flow, table allocation, encryption, troubleshooting), see the shared Vanhoutte Integration and Kassanet Integration docs. This page covers only the reseller-specific path to that integration.
Who can do this
The reseller surface is gated to reseller roles (app/Constants/Roles.php):
reseller-owner(RESELLER_OWNER) — full access; can create and onboard merchantsreseller-administrator(RESELLER_ADMINISTRATOR) — full access; can create and onboard merchantsreseller-rep(RESELLER_REP) — read-only, limited to viewing their own assigned merchants, commissions, and settlements. A reseller-rep cannot open the Clients page or create/onboard merchants (the/clientsroute requiresreseller-analytics, and the create-merchant endpoint is gated to global/owner/administrator viaPermissionService::isGlobalUser).
A global-administrator can also onboard a merchant the same way as reseller-owner/administrator. Reseller-owner, reseller-administrator, and global-admin work happens through client mode (see below), which puts the user into the merchant's context so the normal merchant onboarding applies.
Step 1 — Create the merchant (Client)
Reseller-owners and reseller-administrators (and global-admins via client mode) create and manage merchants from the Clients page (/clients); reseller-reps do not have access to this page. Click to add a client, which opens the create-client dialog (ClientFormDialog.vue). The form collects:
- First name (required)
- Last name (required)
- Email (required)
- Password (required)
- Phone (optional)
- Business name (optional — defaults to "{First name}'s Account" if left blank)
- Country / locale (defaults to Belgium)
- Default language (defaults to English)
Submitting calls POST /api/back-office/partner/merchants (ResellerController::createMerchant → ResellerService::createMerchant). This creates the merchant with onboarding_type = reseller, links it to the reseller (reseller_id), forces a password change on first login (must_change_password = true), and initializes the merchant's tables.
After creation, the reseller can open the client's detail page (/clients/{id}) and use Send Credentials (POST /api/back-office/partner/merchants/{merchantId}/send-credentials) to email the merchant owner a temporary password.
Not verified here: the exact email content/delivery and any reseller-side process steps outside these repos.
Step 2 — Enter client mode
To configure the merchant's POS, branding, location, etc., the reseller switches into client mode (merchantMode, persisted in localStorage). In client mode the reseller/admin operates inside the merchant's context: Emily and Guided Setup use the merchant onboarding endpoints, and the in-house channel grid is filtered to the reseller's assigned POS providers (GET /api/back-office/merchant/reseller-providers, ResellerService::getMerchantResellerProviders).
If a merchant has a reseller, only that reseller's allowed providers are shown; otherwise the provider list falls back to the country/environment-filtered catalog from config/pos-providers.php.
Step 3 — Onboard the merchant (standard Guided Setup)
From client mode, the reseller follows the same Guided Setup / Emily onboarding a self-serve merchant would. There is no separate reseller-specific wizard or reseller-specific question set in code. Step lists come from Emily dynamically, or fall back to the per-provider BASE_SETUP_STEPS. For Vanhoutte the fallback base steps are (see Guided Setup):
- Set up Payment Profile —
/settings/payments - Set up Billing Profile —
/settings/billing - Set up Store Branding —
/settings/brand - Create Location —
/settings/locations - Select Location from Topbar — action:
open_location_selector - Connect Vanhoutte —
/vanhoutte - Sync Menu — the Vanhoutte page
Kiosk and Online Ordering channel checklists unlock after the base steps. Completion is auto-detected by the backend (GET /api/back-office/setup-status) from the merchant's real data, not marked manually.
Note: Although the Guided Setup checklist lists Payment Profile and Billing Profile as steps, the only profile actually enforced at connect time for Vanhoutte is Branding (see "Connecting Vanhoutte" below). Payment and billing profiles are not required to connect the POS.
Connecting Vanhoutte
Route: /vanhoutte
- Select the target location from the topbar.
- Open the Vanhoutte connect dialog (
VanHoutteChannelDialog). - Enter the three credentials (provided by Vanhoutte):
- Connection URL (
base_url) - Signature Key (
signature_key) - Encryption Token (
encryption_token)
- Connection URL (
- Connect, then click Sync Now to import the menu.
Connecting calls POST /api/back-office/kassanet/vanhoutte/{locationId} (the initiate action). The connect dialog collects only those three credentials — there is no sync-time field in the dialog.
Prerequisites enforced at connect time (ThirdPartyIntegrationHelper::checkIntegrationPrerequisites):
- Branding profile must exist, or the connect is rejected ("Missing required profiles: branding profile…"). Payment and billing profiles are optional.
- In-house exclusivity (
checkForInhouseChannel): a location may have only one in-house POS. Hendrickx, Vanhoutte, and ShopCaisse are mutually exclusive per location (IN_HOUSE_CHANNELS), and these also conflict with the merchant-scoped in-house providers Square, MplusKassa, and Lightspeed (IN_HOUSE_MERCHANT_SCOPED_CHANNELS). A conflict is rejected with "Another in-house channel is already enabled for this merchant."
Disconnecting a Vanhoutte integration through the app is currently disabled. To remove or change a connection, contact an administrator.
Auto Sync (sync_time)
The daily auto-sync time is not part of the connect dialog. It is set after connecting, in the Vanhoutte settings form (VanHoutteForm.vue):
- The time picker is time-only (
H:i, 24h) and is snapped to the nearest hour or half-hour (:00or:30). - The time you enter is the location's local time and is stored as that local wall-clock (
settings.sync_time) — not converted to UTC — alongside the resolved zone insettings.sync_timezone. It therefore stays at the same local time across daylight-saving changes. The form shows the resolved zone as a caption under the picker; the merchant does not choose it. - Auto-sync is driven by the
in-house:auto-synccommand, which runs every 30 minutes and triggers a full menu sync for each integration when its scheduled time arrives, so each integration syncs at most once per day. - Clear the field to disable auto-sync.
Reseller Notes
- A reseller can only offer the POS providers assigned to their reseller account; the in-house channel grid is filtered accordingly in client mode.
- Menu items are pulled from Vanhoutte (one-way). The merchant's menu must exist in Vanhoutte before syncing — it cannot be created in Upvendo.
- Vanhoutte requires Branding only to connect; Payment and Billing profiles are optional at connect time (but are still part of the Guided Setup checklist and needed for live ordering — Viva Wallet for Kiosk, Stripe for Online Ordering).
- Created merchants start with
must_change_password = true; the merchant owner sets their own password on first login after receiving credentials.
Not verified here: reseller portal navigation/UX beyond the routes named above, POS-side device/menu setup inside Vanhoutte, billing/invoicing process between reseller and merchant, and any sales/contract steps. These live outside the backend and backoffice repositories.
Related Documentation
- Vanhoutte Integration (full mechanics)
- Hendrickx Integration (twin Kassanet POS)
- Kassanet Integration (shared engine)
- Guided Setup (the onboarding wizard used here)