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) |
Part 7: Encapsulation & Aggregation Rules
7.1 The Encapsulated Template Model
To maximize modularity, templates define dependencies (Variables, Inputs, States) as close to their usage as possible.
- Encapsulation: A
financial_clause_templatecan define its ownvariable_definitions,input_templates, andstate_templates. This ensures that including a "Bonus Clause" automatically tells the system it needs "Bonus Amount" (variable) and "Performance Data" (input). - Aggregation (Hoisting): When a Deal is initialized, the system hoists these nested definitions up to the Clause Block level. The Clause Block becomes the container for all data required by its child clauses.
7.2 Hoisting & Collision Resolution
When multiple financial clauses are instantiated within a single Clause Block:
Shared Variables (Collision = Sharing):
- If two clauses define a variable with the same
variable_key(e.g.,v_base_fee), the system treats them as the same variable. - The user is prompted for the value once, and both clauses reference that single value.
- Example: 3 separate "Base Fee - Year X" clauses all read from one
v_base_feevariable.
- If two clauses define a variable with the same
Instance-Specific Inputs (Collision = Unique):
- If a clause requires unique data per instance (e.g.,
SHOW_DATEfor multiple shows), the template must useallow_multiple: truelogic or distinct keys. - (Standard Pattern: Manual instantiation of distinct clauses implies the user will satisfy unique requirements manually.)
- If a clause requires unique data per instance (e.g.,
7.3 Date Inheritance & Cardinality
Manual Cardinality:
- To create a multi-year term, the user instantiates the "Base Fee" clause template multiple times (once for each year).
- There is no "looping" logic in the template; the Deal Instance simply contains an array of 3 distinct Financial Clause objects.
Date Properties:
- Each
FinancialClauseinstance has its ownstart_dateandend_dateproperties. - These are set during initialization (e.g., Year 1: 2024-2025, Year 2: 2025-2026).
- Each
Inheritance:
- Payment Terms (especially
rule_based) inherit theirstart_dateandend_datefrom their parentFinancialClauseif not explicitly set. - This allows a single "Quarterly Payment" rule to automatically adapt to the specific year of the clause it belongs to.
- Payment Terms (especially
7.4 Dependency Chain & Overrides
The system enforces a strict one-way dependency chain to support User Overrides:
Input -> calculated into -> State -> referenced by -> FinancialClause
- Financial Clauses NEVER look directly at Inputs. They only look at States.
- Why? This allows a user to "Override" a State (e.g., manually set
OPTION_EXERCISED_STATE = true) without changing the Input. The Financial Clause respects the State's final value, regardless of whether it came from calculation or manual intervention.
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.