Skip to content

Config tables

Per-merchant configuration that drives the orchestrator + composer + workers.

MerchantFee — fee rules

Per-merchant rate cards. One row per direction × type × match key with an effective window. Resolved at event time by lib/fees/resolver.ts:pickBestMatch — most specific match wins.

ColumnTypeNotes
merchantIdString
directionFeeDirectionin (Vecnet pays processor) · out (merchant pays Vecnet)
feeTypeFeeTypeacceptance · refund · chargeback · decline · three_ds · antifraud · settlement
channelFeeChannelonline · terminal · any
paymentMethodFeePaymentMethodcard · spei · oxxo · mercadopago · paysafe · terminal_card · any
cardBrandFeeCardBrand?visa · mastercard · amex
cardTypeFeeCardType?credit · debit
installmentsInt?
rateBpsIntBasis points (1 bp = 0.01%)
fixedAmountCentsBigInt
minFeeCents, maxFeeCentsBigInt?Clamp range
ivaRateBpsInt @default(0)IVA in basis points (Mexico = 1600)
ivaIncludedBool @default(false)If true, rate is tax-inclusive and split at calc time
effectiveFrom, effectiveToDateTime

Calculation lives in lib/fees/calculator.ts:

fee = clamp(amountCents * rateBps / 10000 + fixedAmountCents, min, max)

With IVA, calculateFeeWithIva() returns { feeCents, ivaCents, totalCents }.

MerchantRollingReserveConfig

One active config per (merchant, channel). The orchestrator reads the active row on every successful payment and withholds gross * reserveRateBps / 10000 for holdingPeriodDays days.

ColumnTypeNotes
merchantIdString
channelReserveChannelonline · terminal (rolling reserve is channel-scoped)
reserveRateBpsIntBasis points
holdingPeriodDaysInt @default(90)
enabledBool @default(true)
effectiveFrom, effectiveToDateTime

@@unique([merchantId, channel, effectiveFrom]) — append-only config history.

MerchantSettlementConfig — cycle config

One per merchant.

ColumnTypeNotes
cycleTypeSettlementCycleTypedaily · weekly · biweekly · monthly · t_plus_n
weeklyDayOfWeek, biweeklyDayOfWeek, biweeklyAnchorDate, monthlyDayOfMonth, tPlusNvariousCycle-type-specific
timezoneString @default("America/Mexico_City")
minimumPayoutCentsBigInt @default(0)Below this, the cycle rolls into the next
cutoffHourLocalInt @default(17)Local hour the cycle closes
emailRecipientsString[]

Period math lives in lib/settlements/scheduler.ts:computeDuePeriod — returns { start, end } for the most recent cutoff <= now.

MerchantFinanceConfig — module flags

NEW in Phase 1 (Tonder usrv-finances port). Per-merchant booleans mirroring Tonder's ConfigTable. Recorded but not yet enforced by the writers — they're surfaced on the merchant Finance config tab so finops can flip them, with enforcement rolled out per-writer once the product call is made.

prisma
model MerchantFinanceConfig {
  merchantId           String   @id
  enableFees           Boolean  @default(true)
  enableLedger         Boolean  @default(true)
  enableSettlements    Boolean  @default(true)
  enableDailySnapshots Boolean  @default(true)
  updatedAt            DateTime @updatedAt
}

Edited via PATCH /api/admin/merchants/[id]/finance-config; zod schema at lib/schemas/finance-config.ts.

MerchantFeatures — channels + payment methods

ColumnNotes
onlineEnabled, terminalEnabledChannels
cardEnabled, speiEnabled, oxxoEnabled, mercadopagoEnabled, paysafeEnabledPayment methods. "Cash vouchers" label = paysafeEnabled
paymentLinksEnabledOther

MerchantCheckoutConfig — branding only

Logo URL + 4 brand colors. Everything else (locale, footer, button shape, preview, links) was dropped during the Tonder-scope trim.

MerchantApiKey

Live + test keys. The full secret is shown once on creation; the database stores bcrypt-hashed.

AdminUser

Vecnet operators. Bound to Clerk via clerkId. See auth-rls. Holds role (superadmin · finops · integrations), lastLoginAt, audit FKs. No password column — Clerk owns credentials.

Vecnet — Build Spec v0.2 · Obsidian Terminal