Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
/**
 * Organization Framework Module
 *
 * Provides access to organization data and variables for the current user's active org.
 */

import { getApi } from "@/dataAccess/getApi";
import { getDb } from "@/dataAccess/getDb";

/**
 * Pricing-related organization variables
 */
export interface OrgPricingVars {
  hourlyFee: number;
  salesTax: number;
  serviceCallFee: number;
  saDiscount: number;
}

/**
 * Default pricing variables (in base currency XAG)
 * Used when org variables are not set
 */
export const DEFAULT_PRICING_VARS: OrgPricingVars = {
  hourlyFee: 5.257444573770893,    // ~$200/hr at 38.04 XAG/USD
  salesTax: 1.08,                   // 8% tax
  serviceCallFee: 2.0,              // ~$76 service call fee
  saDiscount: 1.0,                  // No discount (1 = 100%)
};

/**
 * Full organization variables (may include additional fields)
 */
export interface OrgVariables extends Partial<OrgPricingVars> {
  preApprovedEmails?: string[];
  [key: string]: any;
}

/**
 * Organization record
 */
export interface OrgRecord {
  id: string;
  name: string;
  owner: string;
  currency?: string;
  variables: OrgVariables;
}

/**
 * Get the current user's active organization ID
 */
export async function getActiveOrgId(): Promise<string | null> {
  const { pb } = await getApi();
  return pb.authStore.record?.activeOrg || null;
}

/**
 * Get organization variables from the local database
 * Returns empty object if no org is found
 */
export async function getOrgVariables(): Promise<OrgVariables> {
  try {
    const { pb } = await getApi();
    const activeOrgId = pb.authStore.record?.activeOrg;

    if (!activeOrgId) {
      return {};
    }

    const db = await getDb();
    const result = await db.dbConn.query(
      `SELECT variables FROM organizations WHERE id = ? LIMIT 1`,
      [activeOrgId]
    );

    if (!result.values || result.values.length === 0) {
      return {};
    }

    const org = result.values[0];
    return org.variables ? JSON.parse(org.variables) : {};
  } catch (e) {
    console.warn("[framework/org] Could not load org variables:", e);
    return {};
  }
}

/**
 * Get pricing variables with defaults for any missing values
 * This is the primary function for getting pricing-related org vars
 */
export async function getPricingVars(): Promise<OrgPricingVars> {
  const orgVars = await getOrgVariables();

  return {
    hourlyFee: orgVars.hourlyFee ?? DEFAULT_PRICING_VARS.hourlyFee,
    salesTax: orgVars.salesTax ?? DEFAULT_PRICING_VARS.salesTax,
    serviceCallFee: orgVars.serviceCallFee ?? DEFAULT_PRICING_VARS.serviceCallFee,
    saDiscount: orgVars.saDiscount ?? DEFAULT_PRICING_VARS.saDiscount,
  };
}

/**
 * Get the full organization record from the local database
 */
export async function getOrg(): Promise<OrgRecord | null> {
  try {
    const { pb } = await getApi();
    const activeOrgId = pb.authStore.record?.activeOrg;

    if (!activeOrgId) {
      return null;
    }

    const db = await getDb();
    const result = await db.dbConn.query(
      `SELECT * FROM organizations WHERE id = ? LIMIT 1`,
      [activeOrgId]
    );

    if (!result.values || result.values.length === 0) {
      return null;
    }

    const org = result.values[0];
    return {
      id: org.id,
      name: org.name,
      owner: org.owner,
      currency: org.currency,
      variables: org.variables ? JSON.parse(org.variables) : {},
    };
  } catch (e) {
    console.warn("[framework/org] Could not load org:", e);
    return null;
  }
}

/**
 * Refresh organization data from the API
 * Call this after org changes to update local cache
 */
export async function refreshOrg(): Promise<void> {
  try {
    const db = await getDb();
    await db.collections.organizations.refresh();
  } catch (e) {
    console.warn("[framework/org] Could not refresh org:", e);
  }
}