bereken_hypotheek_doorstromer
Calculate your maximum mortgage budget for moving to a new home using existing home equity, income details, and current mortgage information.
Instructions
Berekent de maximale hypotheek voor doorstromers (standaard variant). Alle regels uit het doorstromerbeleid gelden ook voor de uitgebreide tool:
Outputvelden (altijd rechtstreeks gebruiken in de terugkoppeling):
max_woningbudget → woningbudget inclusief overwaarde en extra leencapaciteit
overwaarde_bedrag → vrijvallende winst uit de huidige woning
huidige_hypotheek_schuld → resterende schuld die moet worden afgelost
extra_leencapaciteit → nieuwe hypotheekruimte bovenop de overwaarde
maandlast_nu, maandlast_straks en verschil_maandlast → huidige, toekomstige en delta maandlast
Presentatie richting gebruiker (één compact blok):
Toon het woningbudget centraal onder de titel "Uw woningbudget" en licht toe waaruit dit bedrag bestaat in bullets (overwaarde, huidige hypotheek, extra leencapaciteit).
Voeg een tweede blok toe "Uw nieuwe maandlast" met maandlast nu, maandlast straks en het verschil (positief/negatief) op eigen regel.
Gebruik alleen MCP-waarden; geen eigen herberekeningen behalve eenvoudige weergave/afronding.
Invoerkeuze bestaande hypotheek (verplicht expliciet vragen):
Snelle globale berekening → gebruiker geeft een samenvatting (totale schuld, gemiddelde rente/looptijd, eventuele huidige maandlast). Vul één leningdeel met deze totaalwaarden in.
Detailberekening → gebruiker levert alle leningdelen (hoofdsom, rente, resterende looptijd, hypotheekvorm). Kopieer ze één-op-één in de leningdelen array.
Vraag altijd: "Wilt u een snelle globale berekening (met een samenvatting van uw hypotheek) of een detailberekening waarbij u alle leningdelen invoert?" en volg de gekozen route.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| inkomen_aanvrager | Yes | Bruto jaarinkomen hoofdaanvrager in euro's. | |
| geboortedatum_aanvrager | Yes | Interne geboortedatum hoofdaanvrager (ISO). Vraag de gebruiker altijd: "Wat is uw leeftijd of geboortedatum?" en deel bij een leeftijd alleen die leeftijd terug. | |
| heeft_partner | Yes | Geeft aan of een partner mee leent. | |
| inkomen_partner | No | Optioneel partnerinkomen in euro's. | |
| geboortedatum_partner | No | Optionele interne geboortedatum partner (ISO). Vraag ook hier: "Wat is uw leeftijd of geboortedatum?" en houd de afgeleide datum intern. | |
| verplichtingen_pm | No | Optionele maandelijkse verplichtingen in euro's. | |
| waarde_huidige_woning | Yes | Huidige marktwaarde van de bestaande woning. | |
| bestaande_hypotheek | Yes | Bestaande leningdelen voor doorstromer (detailuitleg: hypotheek://v4/guide/opzet-intake). VRAAG ALTIJD: "Wilt u een snelle globale berekening (met een samenvatting van uw hypotheek) of een detailberekening waarbij u alle leningdelen invoert?" | |
| session_id | No | Optioneel sessie-ID vanuit n8n (voor logging). |
Implementation Reference
- src/index.ts:550-579 (handler)Handler function that processes the tool call: normalizes arguments, validates input, constructs API payload, calls the Replit API for mortgage calculation, logs success, and formats the response specifically for doorstromer scenarios.async function handleBerekenDoorstromer(request: any): Promise<ToolResponse> { const rawArgs = requireArguments<DoorstromerArguments>(request); const normalizedArgs = normalizeDoorstromerArgs(rawArgs) as DoorstromerArguments; const logger = createLogger(normalizedArgs.session_id); validateDoorstromerArguments(normalizedArgs); enforceRateLimit(normalizedArgs.session_id); const payload: any = { aanvragers: mapAanvragers(normalizedArgs), bestaande_hypotheek: { waarde_huidige_woning: normalizedArgs.waarde_huidige_woning, leningdelen: normalizedArgs.bestaande_hypotheek.leningdelen, }, }; if (normalizedArgs.session_id) { payload.session_id = normalizedArgs.session_id; } const apiClient = getApiClient(); const { data } = await apiClient.post( REPLIT_API_URL_BEREKENEN, payload, { correlationId: normalizedArgs.session_id } ); logger.info('Toolcall succesvol', { tool: 'bereken_hypotheek_doorstromer' }); return successResponse(formatResponse(data, "bereken_hypotheek_doorstromer")); }
- src/index.ts:799-826 (schema)Input schema definition for the tool, including properties like base intake fields, waarde_huidige_woning, bestaande_hypotheek (with leningdelen), and required fields. Used in ListTools response.{ name: "bereken_hypotheek_doorstromer", description: `Maximale hypotheek voor doorstromers ZONDER concrete woning. Gebruik dit wanneer de gebruiker wil weten hoeveel ruimte er is om straks te verhuizen maar er nog geen koopsom of specifieke woning op tafel ligt. Zodra een concreet huis ter sprake komt schakelt u over op de opzet-hypotheek tools. Alle regels uit het doorstromerbeleid gelden ook voor de uitgebreide tool: ${DOORSTROMER_OUTPUT_GUIDANCE}`, inputSchema: { type: "object", description: `Gebruik basisintakevelden plus huidige woninginformatie; zie ${OPZET_GUIDE_URI} voor detaildefinities.`, properties: { ...baseIntakeProperties, waarde_huidige_woning: { type: "number", description: "Huidige marktwaarde van de bestaande woning.", }, bestaande_hypotheek: { ...bestaandeHypotheekSchema, }, session_id: { type: "string", description: "Optioneel sessie-ID vanuit n8n (voor logging).", }, }, required: [ ...baseIntakeRequired, "waarde_huidige_woning", "bestaande_hypotheek", ], }, },
- src/index.ts:766-774 (registration)TOOL_HANDLERS object registering 'bereken_hypotheek_doorstromer' to its handler function handleBerekenDoorstromer. Used by the CallToolRequestSchema handler to dispatch tool calls.const TOOL_HANDLERS: Record<string, ToolHandler> = { bereken_hypotheek_starter: handleBerekenStarter, bereken_hypotheek_doorstromer: handleBerekenDoorstromer, bereken_hypotheek_uitgebreid: handleBerekenUitgebreid, haal_actuele_rentes_op: handleActueleRentes, opzet_hypotheek_starter: handleOpzetStarter, opzet_hypotheek_doorstromer: handleOpzetDoorstromer, opzet_hypotheek_uitgebreid: handleOpzetUitgebreid, };
- Helper function to normalize doorstromer-specific arguments, mapping variant field names (e.g., existing_mortgage to bestaande_hypotheek) and normalizing leningdelen structure for consistent API payload.export function normalizeDoorstromerArgs(args: any): any { if (!args || typeof args !== 'object') { logger.warn('Invalid doorstromer args input', { args }); return args; } const normalized: any = { ...args }; for (const key of Object.keys(normalized)) { const lowerKey = key.toLowerCase().trim(); const isBestaandeHypotheek = (lowerKey.includes('bestaande') || lowerKey.includes('existing') || lowerKey.includes('current')) && (lowerKey.includes('hypotheek') || lowerKey.includes('lening') || lowerKey.includes('mortgage') || lowerKey.includes('loan')); if (isBestaandeHypotheek) { logger.debug('Normalizing bestaande_hypotheek', { original_key: key }); normalized.bestaande_hypotheek = normalizeBestaandeHypotheek(normalized[key]); if (key !== 'bestaande_hypotheek') { delete normalized[key]; } } const isWoningwaarde = (lowerKey.includes('waarde') && lowerKey.includes('woning')) || (lowerKey.includes('home') && lowerKey.includes('value')); if (isWoningwaarde && typeof normalized[key] === 'number') { logger.debug('Normalizing waarde_huidige_woning', { original_key: key }); normalized.waarde_huidige_woning = normalized[key]; if (key !== 'waarde_huidige_woning') { delete normalized[key]; } } } logger.info('Normalization complete', { has_bestaande_hypotheek: !!normalized.bestaande_hypotheek, has_leningdelen: !!normalized.bestaande_hypotheek?.leningdelen, leningdelen_count: normalized.bestaande_hypotheek?.leningdelen?.length || 0 }); return normalized; }
- src/validation/schemas.ts:331-366 (helper)Validation function specific to doorstromer arguments: validates base args, current home value range, and requires/validates bestaande_hypotheek structure including leningdelen.export function validateDoorstromerArguments(args: unknown): void { // Eerst base arguments valideren validateBaseArguments(args); const input = args as Record<string, unknown>; // Valideer woningwaarde if (typeof input.waarde_huidige_woning !== 'number') { throw new ValidationError( ErrorCode.INVALID_INPUT, 'waarde_huidige_woning moet een getal zijn', 'waarde_huidige_woning' ); } if (input.waarde_huidige_woning < ValidationConstraints.WONING_WAARDE.MIN || input.waarde_huidige_woning > ValidationConstraints.WONING_WAARDE.MAX) { throw new ValidationError( ErrorCode.WONING_VALUE_OUT_OF_RANGE, `Woningwaarde moet tussen €${ValidationConstraints.WONING_WAARDE.MIN.toLocaleString('nl-NL')} en €${ValidationConstraints.WONING_WAARDE.MAX.toLocaleString('nl-NL')} liggen`, 'waarde_huidige_woning', input.waarde_huidige_woning ); } // Valideer bestaande hypotheek if (!input.bestaande_hypotheek) { throw new ValidationError( ErrorCode.INVALID_INPUT, 'bestaande_hypotheek is verplicht voor doorstromers', 'bestaande_hypotheek' ); } validateBestaandeHypotheek(input.bestaande_hypotheek); }