Template System
Overview
Templates define the structure of a deal without specifying actual values. When a user initializes a deal from a template, they provide the specific values (guarantee amounts, percentages, dates, etc.). Once initialized, the deal is completely independent from the template.
Key Principles:
- Templates define what variables, states, inputs, and financial clauses exist
- Initialization defines values for those structures
- Deals are independent after initialization (no re-sync)
- Users can create deals without templates (following grammar/lexicon)
- Users can add/remove optional elements at initialization
Part 1: Template Structure
1.1 Template Document Schema
{
// Identification
template_id: "tpl_guarantee_vs_nbor_001",
template_name: "Guarantee vs Percentage of NBOR",
template_version: "1.0",
// Metadata
description: "Standard touring deal with artist receiving greater of guarantee or percentage of net box office receipts",
deal_type: "guarantee_vs_percentage_nbor",
created_at: "2025-01-01T00:00:00Z",
created_by: "system",
// Variable Definitions (values provided at initialization)
variable_definitions: [
{
variable_key: "v_guarantee",
name: "Artist Guarantee",
type: "number",
required: true,
default_value: null, // No default; user must provide
description: "Fixed minimum payment to artist regardless of ticket sales",
validation: {
min: 0,
max: null
}
},
{
variable_key: "v_artist_percentage",
name: "Artist Percentage",
type: "number",
required: true,
default_value: null,
description: "Percentage of NBOR paid to artist (0-100)",
validation: {
min: 0,
max: 100
}
},
{
variable_key: "v_tax_rate",
name: "Sales Tax Rate",
type: "number",
required: false,
default_value: 0.0825, // Default 8.25%
description: "Local sales tax rate as decimal",
validation: {
min: 0,
max: 0.25
}
}
],
// Clause Block Templates
clause_block_templates: [
{
clause_block_template_id: "cbt_show_performance",
name: "Show Performance",
description: "Standard clause block for a single show performance",
is_required: true,
allow_multiple: true, // Can have multiple shows
// State Templates
state_templates: [
{
state_key: "SHOW_STATE",
state_type: "boolean",
name: "Show Played",
is_required: true,
default_status: "F",
calculation_template: "SHOW_DATE_INPUT.value.date < today() && SHOW_DATE_INPUT.value.status == 'confirmed'"
},
{
state_key: "SHOW_SETTLED",
state_type: "object",
name: "Show Settlement",
is_required: true,
default_status: "F",
calculation_template: {
type: "aggregate",
fields: {
gross_box_office: "TICKET_DETAIL_INPUT.value.total_amount",
sales_tax_collected: "TICKET_DETAIL_INPUT.value.total_amount * v_tax_rate / (1 + v_tax_rate)",
facility_fees: "FACILITY_FEE_INPUT.value.amount_per_ticket * TICKET_DETAIL_INPUT.value.quantity",
net_box_office_receipts: "TICKET_DETAIL_INPUT.value.total_amount - this.facility_fees - this.sales_tax_collected"
}
}
}
],
// Input Templates
input_templates: [
{
input_key: "SHOW_DATE_INPUT",
input_type: "object",
name: "Show Date & Confirmation",
is_required: true,
default_status: "P",
schema: {
date: { type: "date", required: true },
status: { type: "string", enum: ["unconfirmed", "confirmed", "cancelled"], required: true }
}
},
{
input_key: "TICKET_DETAIL_INPUT",
input_type: "object",
name: "Ticket Sales Data",
is_required: true,
default_status: "P",
schema: {
tier: { type: "string", required: false },
quantity: { type: "number", required: true, min: 0 },
price_per_ticket: { type: "number", required: true, min: 0 },
total_amount: { type: "number", required: true, min: 0 },
sales_source: { type: "string", enum: ["box_office", "advance", "will_call"], required: false },
notes: { type: "string", required: false }
}
},
{
input_key: "FACILITY_FEE_INPUT",
input_type: "object",
name: "Facility Fees",
is_required: true,
default_status: "P",
schema: {
amount_per_ticket: { type: "number", required: true, min: 0 },
breakdown: {
type: "array",
items: {
description: { type: "string" },
amount_per_ticket: { type: "number" }
}
}
}
}
],
// Clause Templates
financial_clause_templates: [
{
clause_template_id: "ct_guarantee_vs_nbor",
name: "Guarantee vs NBOR",
is_required: true,
trigger_template: "SHOW_SETTLED.status == 'C' || SHOW_SETTLED.status == 'F'",
calculation_template: "MAX((SHOW_SETTLED.value.net_box_office_receipts * v_artist_percentage / 100), v_guarantee)",
requires_date_range: true,
payment_terms_template: [
{
payment_term_id: "pt_guarantee_01",
payment_term_name: "Guarantee Payment",
payment_type: "lump_sum",
amount: { type: "percentage", value: 100 },
due_date: { type: "relative", trigger: "SHOW_SETTLED.status == 'C'", offset_days: 0 }
}
]
}
]
// Optional: Non-financial clause templates
benefit_clause_templates: [],
obligation_clause_templates: [],
other_clause_templates: []
},
// Optional Merchandise Clause Block
{
clause_block_template_id: "cbt_merchandise_split",
name: "Merchandise Split",
description: "Optional clause block for merchandise revenue sharing",
is_required: false, // User can choose to include or not
allow_multiple: false, // Only one per deal typically
// Additional variable for this clause block
additional_variables: [
{
variable_key: "v_merch_artist_percentage",
name: "Merch Artist Percentage",
type: "number",
required: true,
default_value: 80,
validation: { min: 0, max: 100 }
},
{
variable_key: "v_venue_hall_fee_percentage",
name: "Venue Hall Fee Percentage",
type: "number",
required: true,
default_value: 20,
validation: { min: 0, max: 50 }
}
],
state_templates: [
{
state_key: "MERCH_STATE",
state_type: "object",
name: "Merchandise Data",
is_required: true,
default_status: "F",
calculation_template: "MERCH_DATA_INPUT"
}
],
input_templates: [
{
input_key: "MERCH_DATA_INPUT",
input_type: "object",
name: "Merchandise Sales",
is_required: true,
default_status: "P",
schema: {
gross_merch_sales: { type: "number", required: true, min: 0 },
venue_hall_fee: { type: "number", required: true, min: 0 }
}
}
],
financial_clause_templates: [
{
clause_template_id: "ct_merch_artist_payment",
name: "Merchandise Artist Payment",
is_required: true,
trigger_template: "EXISTS(MERCH_STATE)",
calculation_template: "(MERCH_STATE.value.gross_merch_sales - MERCH_STATE.value.venue_hall_fee) * v_merch_artist_percentage / 100",
payment_terms_template: [
{
payment_term_id: "pt_merch_01",
payment_term_name: "100% Merch Payment",
payment_type: "lump_sum",
amount: { type: "percentage", value: 100 },
due_date: { type: "relative", trigger: "SHOW_SETTLED.status == 'C'", offset_days: 0 }
}
]
}
],
// Optional: Non-financial clause templates
benefit_clause_templates: [],
obligation_clause_templates: [],
other_clause_templates: []
}
],
// Tour Summary Clause Block (optional, for multi-show deals)
{
clause_block_template_id: "cbt_tour_summary",
name: "Tour Summary",
description: "Aggregates all show clause blocks for tour total",
is_required: false,
allow_multiple: false,
state_templates: [
{
state_key: "TOTAL_ARTIST_PAYMENT",
state_type: "number",
name: "Total Artist Payment",
is_required: true,
default_status: "F",
calculation_template: "SUM(cb.financial_clauses[0].amount for cb in ALL_SHOW_CLAUSE_BLOCKS where cb.financial_clauses[0].trigger == true)"
}
],
input_templates: [],
clause_templates: [
{
clause_template_id: "ct_tour_total",
name: "Tour Total Payment",
is_required: true,
trigger_template: "true",
calculation_template: "TOTAL_ARTIST_PAYMENT.value"
}
]
}
}Part 2: Initialization Process
2.1 Initialization Flow
┌─────────────────────────────────────────────────────────────┐
│ TEMPLATE SELECTION │
│ │
│ User selects: "Guarantee vs Percentage of NBOR" │
│ OR │
│ User chooses: "Create from scratch" │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ DEAL METADATA ENTRY │
│ │
│ - Deal name: "Spring Tour 2025 - West Coast" │
│ - Artist: [Select from artist list] │
│ - Promoter: [Select from promoter list] │
│ - Deal type: guarantee_vs_percentage_nbor │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ VARIABLE VALUE ENTRY │
│ │
│ Required Variables: │
│ - v_guarantee: [________] (e.g., 5000) │
│ - v_artist_percentage: [________] (e.g., 85) │
│ │
│ Optional Variables: │
│ - v_tax_rate: [0.0825] (default, can modify) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ CLAUSE BLOCK CONFIGURATION │
│ │
│ Required Clause Blocks: │
│ ☑ Show Performance (x3 for 3 shows) │
│ - Show 1: The Fonda, Dec 15 │
│ - Show 2: The Greek, Dec 18 │
│ - Show 3: The Wiltern, Dec 20 │
│ │
│ Optional Clause Blocks: │
│ ☑ Merchandise Split (include) │
│ - v_merch_artist_percentage: 80 │
│ - v_venue_hall_fee_percentage: 20 │
│ ☐ Tour Summary (not included) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ OPTIONAL CUSTOMIZATION │
│ │
│ Add Extra Elements: │
│ [+ Add State] [+ Add Input] [+ Add Financial Clause] │
│ │
│ Remove Optional Elements: │
│ [- Remove FACILITY_FEE_INPUT from Show 2] │
│ │
│ Modify Calculations: │
│ [Edit calculation for SHOW_SETTLED] │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ DEAL CREATION │
│ │
│ System creates: │
│ - New deal document │
│ - First version (status: "working") │
│ - All clause blocks with structure from template │
│ - All variables with values from user │
│ - All states with calculations from template │
│ - All inputs with default status (P) │
│ - All financial clauses with calculations from template │
│ │
│ Deal is now INDEPENDENT from template. │
└─────────────────────────────────────────────────────────────┘2.2 Initialization Rules
| Rule | Description |
|---|---|
| Required variables must have values | Cannot initialize without v_guarantee if template marks it required |
| Required clause blocks must be included | Cannot skip Show Performance if is_required: true |
| Optional clause blocks can be skipped | User choice to include merchandise split |
| Optional elements within blocks can be removed | Can remove FACILITY_FEE_INPUT if not needed |
| Extra elements can be added | User can add custom states, inputs, financial clauses beyond template |
| Calculations can be modified | User can edit calculation formulas at initialization |
| Variables can be added | User can add v_custom_bonus not in template |
| Deal is independent after init | Changing template does NOT affect existing deals |
2.3 Initialization API
// Request to initialize deal from template
POST /api/deals/initialize
{
template_id: "tpl_guarantee_vs_nbor_001", // or null for from-scratch
deal_metadata: {
name: "Spring Tour 2025 - West Coast",
artist_id: "artist_taylor_swift",
promoter_id: "promoter_live_nation",
deal_type: "guarantee_vs_percentage_nbor"
},
variable_values: {
v_guarantee: 5000,
v_artist_percentage: 85,
v_tax_rate: 0.0925 // Override default
},
clause_block_config: {
// Required blocks
show_performances: [
{
name: "Show 1 - The Fonda",
metadata: { venue: "The Fonda", date: "2025-12-15" },
variable_overrides: {} // Use deal-level variables
},
{
name: "Show 2 - The Greek",
metadata: { venue: "The Greek", date: "2025-12-18" },
variable_overrides: {
v_guarantee: 7500 // Higher guarantee for this show
}
},
{
name: "Show 3 - The Wiltern",
metadata: { venue: "The Wiltern", date: "2025-12-20" },
variable_overrides: {}
}
],
// Optional blocks
include_merchandise_split: true,
merchandise_split_config: {
v_merch_artist_percentage: 80,
v_venue_hall_fee_percentage: 20
},
include_tour_summary: false
},
customizations: {
// Extra elements to add
extra_states: [],
extra_inputs: [],
extra_financial_clauses: [],
// Elements to remove (by key)
remove_states: [],
remove_inputs: [],
remove_financial_clauses: [],
// Calculation overrides
calculation_overrides: {}
}
}
// Response
{
success: true,
deal_id: "deal_spring_tour_2025_abc123",
working_version_id: "v_working_001",
message: "Deal initialized successfully with 4 clause blocks"
}Part 3: Template Examples
3.1 Flat Guarantee Template
{
template_id: "tpl_flat_guarantee_001",
template_name: "Flat Guarantee",
deal_type: "flat_guarantee",
variable_definitions: [
{
variable_key: "v_guarantee",
name: "Artist Guarantee",
type: "number",
required: true,
default_value: null
}
],
clause_block_templates: [
{
clause_block_template_id: "cbt_show_guarantee",
name: "Show Guarantee",
is_required: true,
allow_multiple: true,
state_templates: [
{
state_key: "SHOW_STATE",
state_type: "boolean",
name: "Show Played",
is_required: true,
default_status: "F",
calculation_template: "SHOW_DATE_INPUT.value.date < today() && SHOW_DATE_INPUT.value.status == 'confirmed'"
}
],
input_templates: [
{
input_key: "SHOW_DATE_INPUT",
input_type: "object",
name: "Show Confirmation",
is_required: true,
default_status: "P",
schema: {
date: { type: "date", required: true },
status: { type: "string", enum: ["unconfirmed", "confirmed", "cancelled"] }
}
}
],
financial_clause_templates: [
{
clause_template_id: "ct_guarantee",
name: "Guarantee Payment",
is_required: true,
trigger_template: "SHOW_STATE.value == true",
calculation_template: "v_guarantee",
payment_terms_template: [
{
payment_term_id: "pt_guarantee_01",
payment_term_name: "Guarantee Payment",
payment_type: "lump_sum",
amount: { type: "percentage", value: 100 },
due_date: { type: "absolute", value: "SHOW_DATE_INPUT.value.date" }
}
]
}
]
}
]
}3.2 Split Point Deal Template
{
template_id: "tpl_split_point_001",
template_name: "Split Point Deal",
deal_type: "split_point",
variable_definitions: [
{
variable_key: "v_guarantee",
name: "Artist Guarantee",
type: "number",
required: true
},
{
variable_key: "v_artist_overage_percentage",
name: "Artist Overage Percentage",
type: "number",
required: true,
default_value: 85,
validation: { min: 0, max: 100 }
},
{
variable_key: "v_promoter_profit_percentage",
name: "Promoter Profit Percentage",
type: "number",
required: true,
default_value: 15,
validation: { min: 0, max: 50 }
},
{
variable_key: "v_tax_rate",
name: "Sales Tax Rate",
type: "number",
required: false,
default_value: 0.0825
}
],
clause_block_templates: [
{
clause_block_template_id: "cbt_split_point_show",
name: "Split Point Show",
is_required: true,
allow_multiple: true,
state_templates: [
{
state_key: "SHOW_STATE",
state_type: "boolean",
name: "Show Played",
is_required: true
},
{
state_key: "SHOW_SETTLED",
state_type: "object",
name: "Show Settlement",
is_required: true,
calculation_template: {
gross_box_office: "TICKET_DETAIL_INPUT.value.total_amount",
sales_tax: "TICKET_DETAIL_INPUT.value.total_amount * v_tax_rate / (1 + v_tax_rate)",
facility_fees: "FACILITY_FEE_INPUT.value.amount_per_ticket * TICKET_DETAIL_INPUT.value.quantity",
net_box_office: "this.gross_box_office - this.sales_tax - this.facility_fees"
}
},
{
state_key: "SPLIT_POINT_CALC",
state_type: "object",
name: "Split Point Calculation",
is_required: true,
calculation_template: {
total_expenses: "EXPENSE_INPUT.value.total",
promoter_profit: "this.total_expenses * v_promoter_profit_percentage / 100",
split_point: "v_guarantee + this.total_expenses + this.promoter_profit",
overage: "MAX(0, SHOW_SETTLED.value.net_box_office - this.split_point)",
artist_backend: "this.overage * v_artist_overage_percentage / 100"
}
}
],
input_templates: [
{
input_key: "SHOW_DATE_INPUT",
is_required: true
},
{
input_key: "TICKET_DETAIL_INPUT",
is_required: true
},
{
input_key: "FACILITY_FEE_INPUT",
is_required: true
},
{
input_key: "EXPENSE_INPUT",
input_type: "object",
name: "Show Expenses",
is_required: true,
default_status: "P",
schema: {
total: { type: "number", required: true, min: 0 },
breakdown: {
type: "array",
items: {
category: { type: "string" },
amount: { type: "number" },
is_variable: { type: "boolean" }
}
}
}
}
],
clause_templates: [
{
clause_template_id: "ct_split_point_payment",
name: "Split Point Artist Payment",
is_required: true,
trigger_template: "SHOW_SETTLED.status != 'D'",
calculation_template: "v_guarantee + SPLIT_POINT_CALC.value.artist_backend"
}
]
}
]
}3.3 Endorsement Deal with Non-Financial Clauses
This template demonstrates how to include benefit, obligation, and other clause templates alongside financial clauses.
{
template_id: "tpl_endorsement_001",
template_name: "Brand Endorsement with Benefits and Obligations",
deal_type: "custom",
variable_definitions: [
{
variable_key: "v_base_fee",
name: "Monthly Base Fee",
type: "number",
required: true,
default_value: null
},
{
variable_key: "v_bonus_amount",
name: "Performance Bonus",
type: "number",
required: true,
default_value: 10000
}
],
clause_block_templates: [
{
clause_block_template_id: "cbt_endorsement_main",
name: "Endorsement Agreement",
is_required: true,
allow_multiple: false,
state_templates: [
{
state_key: "POSTS_COMPLETED",
state_type: "number",
name: "Posts Completed",
is_required: true,
default_status: "C",
calculation_template: "SOCIAL_POSTS_INPUT.value.count"
}
],
input_templates: [
{
input_key: "SOCIAL_POSTS_INPUT",
input_type: "object",
name: "Social Media Posts",
is_required: true,
default_status: "P",
schema: {
count: { type: "number", required: true },
platforms: { type: "array", required: true },
month: { type: "string", required: true }
}
}
],
clause_templates: [
{
clause_template_id: "ct_base_fee",
name: "Monthly Base Fee",
is_required: true,
trigger_template: "true",
calculation_template: "v_base_fee"
},
{
clause_template_id: "ct_performance_bonus",
name: "Performance Bonus",
is_required: false,
trigger_template: "POSTS_COMPLETED.value >= 4",
calculation_template: "v_bonus_amount"
}
],
benefit_clause_templates: [
{
benefit_clause_template_id: "bct_product_allotment",
benefit_clause_name: "Product Allotment",
benefit_type: "goods",
benefit_direction: "to_client",
is_required: false,
description_template: "Client receives {cases_per_month} cases of product per month",
quantitative_terms_template: {
caps: {
cases_per_month: 24
},
units: "cases"
}
},
{
benefit_clause_template_id: "bct_event_access",
benefit_clause_name: "VIP Event Access",
benefit_type: "access",
benefit_direction: "to_client",
is_required: false,
description_template: "VIP access to all brand-sponsored events for client and {max_guests} guests"
}
],
obligation_clause_templates: [
{
obligation_clause_template_id: "oct_social_posts",
obligation_clause_name: "Social Media Posts",
obligation_type: "promotion",
party: "client",
is_required: true,
description_template: "Post {min_posts_per_month} times per month on specified platforms",
obligation_detail_template: {
metrics: {
min_posts_per_month: 4,
platforms: ["instagram", "tiktok"]
},
approval_required: true,
approval_sla_hours: 72
}
},
{
obligation_clause_template_id: "oct_exclusivity",
obligation_clause_name: "Category Exclusivity",
obligation_type: "exclusivity",
party: "client",
is_required: true,
description_template: "No endorsement of competing {category} brands during term",
obligation_detail_template: {
metrics: {
excluded_categories: ["beverages", "energy_drinks"]
}
}
}
],
other_clause_templates: [
{
other_clause_template_id: "oct_term",
other_clause_name: "Term and Territory",
other_clause_type: "term",
is_required: true,
description_template: "12-month agreement from {start_date}, {territory}",
key_terms_template: {
term: {
duration_months: 12,
auto_renew: false,
renewal_notice_deadline_days: 30
},
territory: {
regions_included: ["worldwide"],
regions_excluded: []
}
}
}
]
}
]
}Part 4: Creating Deals Without Templates
Users can create deals from scratch without a template, as long as they follow the grammar/lexicon:
4.1 Required Structure
// Minimum valid deal structure
{
deal_id: "deal_custom_001",
deal_type: "custom", // Or specific type
artist_id: "...",
promoter_id: "...",
name: "...",
initialized_from_template: null, // No template
versions: [
{
version_id: "v_001",
status: "working",
clause_blocks: [
{
clause_block_id: "cb_001",
clause_block_ref: "CB_MAIN",
name: "Main Clause Block",
static_variables: {}, // At least empty object
states: [], // At least empty array
inputs: [], // At least empty array
financial_clauses: [], // At least empty array
// Optional: Can be omitted or included as empty arrays
benefit_clauses: [], // Optional
obligation_clauses: [], // Optional
other_clauses: [] // Optional
}
]
}
]
}4.2 Grammar Rules
| Element | Requirements |
|---|---|
| Deal | Must have deal_id, deal_type, artist_id, promoter_id |
| Version | Must have version_id, status, clause_blocks array |
| Clause Block | Must have clause_block_id, clause_block_ref, name |
| State | Must have state_key (unique within block), state_type, value |
| Input | Must have input_key (unique within block), input_type, value, status |
| Financial Clause | Must have clause_id, name, trigger, calculation |
| Reference | Must use valid reference syntax (see Reference Syntax section) |
4.3 Validation on Save
When user saves a working version (from-scratch or template), system validates:
- All required fields present
- All state_keys unique within clause_block
- All input_keys unique within clause_block
- All clause_block_refs unique within version
- All references resolve to existing elements
- No circular dependencies
- All calculations syntactically valid
Part 5: Template Versioning
5.1 Template Version Rules
- Templates can have multiple versions (v1, v2, v3)
- When initializing, user selects specific template version
- Deals track which template version they were initialized from (informational only)
- Updating a template to v2 does NOT affect deals initialized from v1
- Old template versions remain available for reference
5.2 Template Update Process
Template: "Guarantee vs NBOR" v1
↓
[Admin adds new optional clause block]
↓
Template: "Guarantee vs NBOR" v2
↓
Existing deals (from v1): UNCHANGED
New deals: Can choose v1 or v25.3 Template Deprecation
{
template_id: "tpl_guarantee_vs_nbor_001",
template_version: "1.0",
status: "deprecated", // "active" | "deprecated" | "archived"
deprecated_at: "2025-06-01T00:00:00Z",
deprecated_reason: "Superseded by v2 with improved expense handling",
replacement_template_id: "tpl_guarantee_vs_nbor_002"
}- Deprecated templates: Not shown in template picker by default
- Archived templates: Completely hidden, only visible in admin
- Deals initialized from deprecated templates: Still function normally
Part 6: Template vs. Deal Comparison
| Aspect | Template | Deal (Initialized) |
|---|---|---|
| Contains actual values | No (just definitions) | Yes |
| Can be modified | Yes (creates new version) | Yes (creates new version) |
| Affects other entities when changed | No (deals are independent) | No (versions are independent) |
| Has multiple versions | Yes | Yes |
| Has clause_blocks | Template definitions | Actual instances |
| Has states/inputs | Schema definitions | Actual values |
| Can be deleted | Yes (if no deals reference) | Yes (but audit concern) |
Conclusion
The Template System provides:
- Reusability: Define deal structure once, use many times
- Flexibility: Users can customize at initialization
- Independence: Deals are not tied to template after init
- Extensibility: Add elements beyond template
- Clarity: Template version tracking for audit
Templates are the starting point, not the constraint. Users have full control to:
- Use templates as-is
- Modify templates at initialization
- Create deals from scratch
- Add/remove elements freely
This enables standardization where helpful while preserving flexibility for unique deal structures.