PricingDeep DiveLevel 2 - Post-Process Deep Dives

Creating a Custom Post-Process

A guide to building a custom post-process equation from one of three templates - flat fee, percentage of process price, or geometry-based - plus shared rules for all post-process equations.

Overview

Most post-processes can be built from one of three templates. Choose the one that matches how your cost scales, then modify the numbers.


Template 1 - Flat fee

Use when: the post-process costs roughly the same regardless of part size (e.g. inspection, marking, labelling, packaging).

// Level 2 equation
const FLAT_FEE  = variable('Post-process cost', 8.00)
const unitPrice = variable('unitPrice', round(FLAT_FEE, 2))
done(unitPrice)

That's it. The operator can override the fee per order if needed.


Template 2 - Percentage of process price

Use when: the post-process adds a proportional cost relative to the part's base price (e.g. premium finishing, quality inspection tier).

// Level 2 equation
const PERCENTAGE = variable('Percentage price increase', 0.15)  // 15%
const unitPrice  = variable('unitPrice', round(processPricing.price * PERCENTAGE, 2))
done(unitPrice)

processPricing.price is the unit price returned by the Level 1 equation for this part.


Template 3 - Geometry-based

Use when: cost depends on part size. Choose the right geometry metric:

Cost driverUseExample
Surface treatedspecification.areaPainting, plating, coating, blasting
Material consumedspecification.volume or shrinkWrapVolumeResin coating, impregnation
Part weight(volume / 1000) × densityPlating by gram, dyeing by mass
// Level 2 equation — area-based example
const { area } = specification

const ratePerMm2 = variable('Rate per mm²', 0.002)
const MIN_CHARGE = variable('Minimum charge', 5.00)

const calculated = round(area * ratePerMm2, 2)
const unitPrice  = variable('unitPrice', Math.max(MIN_CHARGE, calculated))
done(unitPrice)

Using Level 1 data in Level 2

If your post-process cost depends on something the Level 1 equation calculated (machine time, support volume, machine type), expose it via variable() at Level 1 and read it at Level 2:

// Level 1 (at the end, before done()):
const machineTimeHours = variable('machineTime', round(calculatedTime, 2))
done(unitPrice, machineTimeHours)

// Level 2:
const printTime    = processPricing.variables['machineTime']  // hours
const RATE         = variable('Rate per hour', 3.00)
const unitPrice    = variable('unitPrice', round(printTime * RATE, 2))
done(unitPrice)

Rules for all post-process equations

  1. Always end with done(unitPrice) - do not forget this
  2. Always wrap the final price in variable('unitPrice', ...) - this is the operator's escape hatch
  3. Use reviewRequired when the post-process isn't available for this geometry, colour, or material:
const SUPPORTED_COLORS = ['Black', 'White', 'Grey']
const reviewRequired   = !SUPPORTED_COLORS.includes(specification.color ?? '')
const unitPrice        = variable('unitPrice', calculatedCost)
done(unitPrice, 0, reviewRequired)
  1. Never multiply by requisition.quantity - Phasio does this automatically. Return the unit price for one part.

Last updated on

On this page