Bantai
BANTAI

Business Logic

E-commerce and banking transaction validation examples

Business Logic

Examples of complex business logic validation using Bantai.

E-commerce Order Validation

import { z } from 'zod';
import {
  defineContext,
  defineRule,
  definePolicy,
  evaluatePolicy,
  allow,
  deny,
} from '@bantai-dev/core';

const orderContext = defineContext(
  z.object({
    userId: z.string(),
    items: z.array(
      z.object({
        productId: z.string(),
        quantity: z.number().int().positive(),
        price: z.number().positive(),
      })
    ),
    paymentMethod: z.string(),
    shippingAddress: z.string(),
  })
);

const inventoryRule = defineRule(
  orderContext,
  'check-inventory',
  async (input) => {
    // Check if all items are in stock
    for (const item of input.items) {
      const stock = await getInventory(item.productId);
      if (stock < item.quantity) {
        return deny({
          reason: `Insufficient stock for product ${item.productId}`,
        });
      }
    }
    return allow({ reason: 'All items are in stock' });
  }
);

const quantityRule = defineRule(
  orderContext,
  'check-quantity',
  async (input) => {
    // Check quantity limits
    for (const item of input.items) {
      if (item.quantity > 10) {
        return deny({
          reason: `Quantity limit exceeded for product ${item.productId}`,
        });
      }
    }
    return allow({ reason: 'All quantities are within limits' });
  }
);

const paymentRule = defineRule(
  orderContext,
  'check-payment',
  async (input) => {
    const validMethods = ['credit_card', 'paypal', 'bank_transfer'];
    if (validMethods.includes(input.paymentMethod)) {
      return allow({ reason: 'Payment method is valid' });
    }
    return deny({ reason: 'Invalid payment method' });
  }
);

const orderPolicy = definePolicy(
  orderContext,
  'order-validation-policy',
  [inventoryRule, quantityRule, paymentRule],
  {
    defaultStrategy: 'exhaustive', // Show all validation errors
  }
);

Banking Transaction Validation

const transactionContext = defineContext(
  z.object({
    userId: z.string(),
    accountId: z.string(),
    amount: z.number().positive(),
    transactionType: z.enum(['deposit', 'withdrawal', 'transfer']),
    recipientAccountId: z.string().optional(),
  })
);

const balanceRule = defineRule(
  transactionContext,
  'check-balance',
  async (input) => {
    if (input.transactionType === 'deposit') {
      return allow(); // Deposits don't need balance check
    }
    
    const balance = await getBalance(input.accountId);
    if (balance >= input.amount) {
      return allow({ reason: 'Sufficient balance' });
    }
    return deny({ reason: 'Insufficient balance' });
  }
);

const dailyLimitRule = defineRule(
  transactionContext,
  'check-daily-limit',
  async (input) => {
    const dailyTotal = await getDailyTotal(input.accountId);
    const limit = 10000; // $10,000 daily limit
    
    if (dailyTotal + input.amount <= limit) {
      return allow({ reason: 'Within daily limit' });
    }
    return deny({ reason: 'Daily transaction limit exceeded' });
  }
);

const kycRule = defineRule(
  transactionContext,
  'check-kyc',
  async (input) => {
    // KYC required for large transactions
    if (input.amount < 5000) {
      return allow(); // Small transactions don't need KYC
    }
    
    const kycStatus = await getKYCStatus(input.userId);
    if (kycStatus === 'verified') {
      return allow({ reason: 'KYC verified' });
    }
    return deny({ reason: 'KYC verification required for large transactions' });
  }
);

const bankingPolicy = definePolicy(
  transactionContext,
  'banking-transaction-policy',
  [balanceRule, dailyLimitRule, kycRule],
  {
    defaultStrategy: 'preemptive', // Fail fast on critical checks
  }
);

On this page