import getTokenHelper from "../../utils/getTokenHelper" import refreshTokenHelper from "../../utils/refreshTokenHelper" import errorHandlingHelper from "../../utils/errorHandlingHelper" import fetchHelper from "../../utils/fetchHelper" import { resolveMerchantPartner, pickMerchantFields, MERCHANT_PARTNER_FIELDS } from "../../utils/merchantPartner" /** * Merchant self-service update of the own company partner (C_BPartner). * Writes with the iDempiere service token (limited roles cannot write * c_bpartner), but ONLY keys present in MERCHANT_PARTNER_FIELDS are accepted * — anything else in the body is ignored. The target partner is resolved * server-side from the caller's own identity; the client cannot pick one. */ const handleFunc = async (event: any, authToken: string | null = null) => { const config = useRuntimeConfig() const serviceToken = (config.api as any)?.idempieretoken const token = serviceToken || authToken || await getTokenHelper(event) const body = await readBody(event) // Build the write payload strictly from the whitelist. const updatePayload: Record = {} for (const [key, def] of Object.entries(MERCHANT_PARTNER_FIELDS)) { if (!body || !Object.prototype.hasOwnProperty.call(body, key)) continue const value = String(body[key] ?? '').trim() if (key === 'eMailInvoice') { // Empty clears the field (invoice emails then fall back to the general // partner EMail); otherwise require a plausible address. if (value !== '' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) { return { status: 422, message: 'Invalid email address' } } if (value.length > 254) { return { status: 422, message: 'Email address is too long' } } } updatePayload[def.writeKey] = value } if (Object.keys(updatePayload).length === 0) { return { status: 400, message: 'No editable field in request' } } const partner = await resolveMerchantPartner(event, token) if (!partner) { return { status: 404, message: 'No business partner is linked to this account' } } const res: any = await fetchHelper(event, `models/c_bpartner/${partner.id}`, 'PUT', token, updatePayload) return { status: 200, companyName: res?.Name || partner.record?.Name || '', ...pickMerchantFields(res ?? partner.record) } } export default defineEventHandler(async (event) => { let data: any = {} try { data = await handleFunc(event) } catch (err: any) { try { const authToken: any = await refreshTokenHelper(event) data = await handleFunc(event, authToken) } catch (error: any) { data = errorHandlingHelper(err?.data ?? err, error?.data ?? error) } } return data })