Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
/**
 * TNFR Legacy Formula with Hours (Implied Rate)
 *
 * A JSON-based pricing formula for use with calculatePrice().
 * Calculates an "implied hourly rate" from the tier price,
 * which is then used to price additional time.
 */

export const docs = `
# TNFR Legacy Formula with Hours

A JSON-based pricing formula that calculates service job prices based on materials,
labor time, and various multipliers. Uses an "implied rate" system to price
additional hours based on the calculated tier price.

## Usage

\`\`\`typescript
import tnfrLegacyWithHours from "@/lib/tnfrLegacyWithHours";
import calculatePrice from "@/framework/calculatePrice";

// Create a formula instance
const formula = tnfrLegacyWithHours();

// Optionally set input values
formula.vars.materialCostBase.value = 2.5;
formula.vars.timeCostBase.value = 1.5;

// Calculate price
const result = calculatePrice(costsMaterial, costsTime, formula);
// result.finalPrice - the calculated price
// result.formulaSteps - array of calculation steps
\`\`\`

## Currency Note

All monetary values are in a **base currency unit** (XAG - silver). Use the
currency conversion utilities to convert to display currencies like USD.

## Calculation Steps

1. **Material Fee**: materialCostBase × salesTax × markup (from scale)
2. **Time Fee**: timeCostBase × hourlyFee
3. **Combined Fee**: materialFee + timeFee
4. **Trip Fee**: combinedFee + serviceCallFee
5. **Tier Price**: tripFee × multiplier
6. **Implied Rate**: (tierPrice - materialFee) / timeCostBase
7. **Additional Material**: additionalMaterial × salesTax × markup
8. **Additional Time**: additionalTime × impliedRate × additionalHourDiscount
9. **Leveled Price**: tierPrice + additionalTimeFee + additionalMaterialFee
10. **Final Price**: leveledPrice × standardDeduction × saDiscount

## Implied Rate Calculation

The "implied rate" is an effective hourly rate derived from the tier price. It captures
all pricing factors (tier multiplier, service call fee, base hourly rate) into a single
rate that can be used to price additional hours consistently.

**Formula:**
\`\`\`
impliedTimeFee = tierPrice - materialFee
impliedHourlyRate = impliedTimeFee / timeCostBase
\`\`\`

**Why it works:**
- The tier price includes: (materialFee + timeFee + serviceCallFee) × multiplier
- Subtracting materialFee isolates the "time portion" of the price
- Dividing by base hours gives an effective hourly rate that includes:
  - The base hourly fee
  - The tier multiplier effect
  - A share of the service call fee

**Example:**
- Base time: 1 hour, hourlyFee: 5.262, serviceCallFee: 2, multiplier: 1.2
- timeFee = 1 × 5.262 = 5.262
- tripFee = 0 + 5.262 + 2 = 7.262 (assuming no material)
- tierPrice = 7.262 × 1.2 = 8.714
- impliedTimeFee = 8.714 - 0 = 8.714
- impliedHourlyRate = 8.714 / 1 = 8.714 per hour

Additional hours are then priced at: additionalTime × impliedRate × additionalHourDiscount

**Note:** When timeCostBase is 0, the implied rate will be 0 (division returns 0).

## Input Variables (vars)

| Variable | Default | Unit | Description |
|----------|---------|------|-------------|
| materialCostBase | 0 | currency | Total material cost from offer |
| timeCostBase | 0 | hours | Total time from offer |
| hourlyFee | 5.2574... | currency | Base hourly rate ($200/hr) |
| salesTax | 1.07 | multiplier | Sales tax (7%) |
| serviceCallFee | 1.55 | currency | Trip/service call fee (~$59) |
| multiplier | 1 | multiplier | Tier multiplier |
| saDiscount | 1 | multiplier | SA discount (1 = no discount) |
| standardDeduction | 1 | multiplier | Standard deduction |
| additionalHourDiscount | 0.4 | multiplier | Additional hours discount |
| additionalTime | 0 | hours | Extra time beyond base |
| additionalMaterial | 0 | currency | Extra material cost |
| markupScale | [...] | scale | Tiered markup thresholds |

## Markup Scale

Higher markup for cheaper materials (in base currency):

| Material Cost ≥ | Markup |
|-----------------|--------|
| 6.57 | 1.65× |
| 3.94 | 1.75× |
| 2.63 | 2.00× |
| 1.58 | 2.25× |
| 1.05 | 2.50× |
| 0.53 | 2.75× |
| 0.26 | 3.00× |
| 0.13 | 3.50× |
| 0 | 4.00× |

## Exports

- **default**: Factory function returning a formula object with vars, derivedVars, and operations
- **VarUnit**: Type for variable units ("currency" | "hours" | "multiplier" | "scale")
- **VarMeta**: Interface for variable metadata (value, unit, description)
- **docs**: This documentation string
`;

export type VarUnit = "currency" | "hours" | "multiplier" | "scale";

export interface VarMeta {
  value: number | number[][];
  unit: VarUnit;
  description?: string;
}

export default () => {
  return {
    vars: {
      // Base costs (calculated from offer data)
      materialCostBase: { value: 0, unit: "currency" as VarUnit, description: "Total material cost from offer" },
      timeCostBase: { value: 0, unit: "hours" as VarUnit, description: "Total time from offer" },

      // Organization variables (currency values based on 38.041295 XAG/USD rate)
      hourlyFee: { value: 5.257444573770893, unit: "currency" as VarUnit, description: "Hourly rate ($200/hr)" },
      salesTax: { value: 1.07, unit: "multiplier" as VarUnit, description: "Sales tax multiplier (7%)" },
      serviceCallFee: { value: 1.55, unit: "currency" as VarUnit, description: "Service call / trip fee (~$59)" },
      saDiscount: { value: 1, unit: "multiplier" as VarUnit, description: "Service agreement discount (1 = no discount)" },
      multiplier: { value: 1, unit: "multiplier" as VarUnit, description: "Tier multiplier" },
      standardDeduction: { value: 1.0, unit: "multiplier" as VarUnit, description: "Standard deduction multiplier" },
      additionalHourDiscount: { value: 0.4, unit: "multiplier" as VarUnit, description: "Discount for additional hours" },

      // Additional costs (passed in at calculation time)
      additionalTime: { value: 0, unit: "hours" as VarUnit, description: "Additional time beyond base" },
      additionalMaterial: { value: 0, unit: "currency" as VarUnit, description: "Additional material cost" },

      // Markup scale - same as pricingFormula.ts
      markupScale: {
        value: [
          [6.571805718, 1.65],
          [3.943083431, 1.75],
          [2.628722287, 2],
          [1.577233372, 2.25],
          [1.051488915, 2.5],
          [0.5257444574, 2.75],
          [0.2628722287, 3],
          [0.1314361144, 3.5],
          [0, 4],
        ],
        unit: "scale" as VarUnit,
        description: "Material markup scale [threshold, multiplier]",
      },
    },
    derivedVars: {
      // Material calculations
      taxedMaterialCost: { value: 0, unit: "currency" as VarUnit },
      markupMultiplier: { value: 0, unit: "multiplier" as VarUnit },
      materialFee: { value: 0, unit: "currency" as VarUnit },

      // Time calculations
      timeFee: { value: 0, unit: "currency" as VarUnit },

      // Combined and tier
      combinedFee: { value: 0, unit: "currency" as VarUnit },
      tripFee: { value: 0, unit: "currency" as VarUnit },
      tierPrice: { value: 0, unit: "currency" as VarUnit },

      // Implied rate calculation
      impliedTimeFee: { value: 0, unit: "currency" as VarUnit },
      impliedHourlyRate: { value: 0, unit: "currency" as VarUnit, description: "Implied hourly rate from tier" },

      // Additional material
      additionalMaterialTaxed: { value: 0, unit: "currency" as VarUnit },
      additionalMaterialMarkup: { value: 0, unit: "multiplier" as VarUnit },
      additionalMaterialFee: { value: 0, unit: "currency" as VarUnit },

      // Additional time
      additionalTimeFee: { value: 0, unit: "currency" as VarUnit },
      additionalTimeFeeDiscounted: { value: 0, unit: "currency" as VarUnit },

      // Final calculations
      leveledPrice: { value: 0, unit: "currency" as VarUnit },
      priceAfterDeduction: { value: 0, unit: "currency" as VarUnit },
      finalPrice: { value: 0, unit: "currency" as VarUnit },
    },
    operations: [
      // Step 1: Calculate material fee
      {
        op: "mult",
        in1: "materialCostBase",
        in2: "salesTax",
        out: "taxedMaterialCost",
      },
      {
        op: "scale",
        in1: "markupScale",
        in2: "materialCostBase", // Note: scale on raw material, not taxed (matches pricingFormula.ts)
        out: "markupMultiplier",
      },
      {
        op: "mult",
        in1: "markupMultiplier",
        in2: "taxedMaterialCost",
        out: "materialFee",
      },

      // Step 2: Calculate time fee
      {
        op: "mult",
        in1: "timeCostBase",
        in2: "hourlyFee",
        out: "timeFee",
      },

      // Step 3: Combined fee
      {
        op: "add",
        in1: "materialFee",
        in2: "timeFee",
        out: "combinedFee",
      },

      // Step 4: Add trip fee
      {
        op: "add",
        in1: "combinedFee",
        in2: "serviceCallFee",
        out: "tripFee",
      },

      // Step 5: Apply tier multiplier
      {
        op: "mult",
        in1: "tripFee",
        in2: "multiplier",
        out: "tierPrice",
      },

      // Step 6: Calculate implied hourly rate
      // impliedTimeFee = tierPrice - materialFee
      {
        op: "sub",
        in1: "tierPrice",
        in2: "materialFee",
        out: "impliedTimeFee",
      },
      // impliedHourlyRate = impliedTimeFee / timeCostBase
      {
        op: "div",
        in1: "impliedTimeFee",
        in2: "timeCostBase",
        out: "impliedHourlyRate",
      },

      // Step 7: Calculate additional material fee
      {
        op: "mult",
        in1: "additionalMaterial",
        in2: "salesTax",
        out: "additionalMaterialTaxed",
      },
      {
        op: "scale",
        in1: "markupScale",
        in2: "additionalMaterial",
        out: "additionalMaterialMarkup",
      },
      {
        op: "mult",
        in1: "additionalMaterialMarkup",
        in2: "additionalMaterialTaxed",
        out: "additionalMaterialFee",
      },

      // Step 8: Calculate additional time fee with discount
      {
        op: "mult",
        in1: "additionalTime",
        in2: "impliedHourlyRate",
        out: "additionalTimeFee",
      },
      {
        op: "mult",
        in1: "additionalTimeFee",
        in2: "additionalHourDiscount",
        out: "additionalTimeFeeDiscounted",
      },

      // Step 9: Calculate leveled price
      // leveledPrice = tierPrice + additionalTimeFeeDiscounted + additionalMaterialFee
      {
        op: "add",
        in1: "tierPrice",
        in2: "additionalTimeFeeDiscounted",
        out: "leveledPrice", // temporary, will add material next
      },
      {
        op: "add",
        in1: "leveledPrice",
        in2: "additionalMaterialFee",
        out: "leveledPrice",
      },

      // Step 10: Apply standard deduction
      {
        op: "mult",
        in1: "leveledPrice",
        in2: "standardDeduction",
        out: "priceAfterDeduction",
      },

      // Step 11: Apply SA discount
      {
        op: "mult",
        in1: "priceAfterDeduction",
        in2: "saDiscount",
        out: "finalPrice",
      },
    ],
  };
};