Artifex/control_plane/ventures/models.py

167 lines
7.7 KiB
Python
Raw Normal View History

from __future__ import annotations
from django.db import models
from control_plane.common import TimestampedModel
class CompanyProposalStatus(models.TextChoices):
DRAFT = "DRAFT"
SUBMITTED = "SUBMITTED"
UNDER_DILIGENCE = "UNDER_DILIGENCE"
REVISE = "REVISE"
FUNDED_RECOMMENDED = "FUNDED_RECOMMENDED"
WATCHLIST = "WATCHLIST"
REJECTED = "REJECTED"
class ICDecisionType(models.TextChoices):
FUND_RECOMMENDED = "FUND_RECOMMENDED"
CONDITIONAL_FUND = "CONDITIONAL_FUND"
REVISE_AND_RESUBMIT = "REVISE_AND_RESUBMIT"
WATCHLIST = "WATCHLIST"
PIVOT = "PIVOT"
REJECT = "REJECT"
class CapabilityStatus(models.TextChoices):
AVAILABLE = "AVAILABLE"
PARTIAL = "PARTIAL"
MISSING = "MISSING"
class CapabilityPriority(models.TextChoices):
BEFORE_VALIDATION = "BEFORE_VALIDATION"
BEFORE_FIRST_CUSTOMER = "BEFORE_FIRST_CUSTOMER"
BEFORE_SCALING = "BEFORE_SCALING"
class CompanyMandate(TimestampedModel):
objective = models.TextField()
constraints = models.JSONField(default=dict, blank=True)
optimization_targets = models.JSONField(default=list, blank=True)
max_validation_capital = models.DecimalField(max_digits=10, decimal_places=2, default=50)
target_net_new_cash = models.DecimalField(max_digits=10, decimal_places=2, default=500)
target_window_days = models.PositiveIntegerField(default=30)
metadata = models.JSONField(default=dict, blank=True)
class VentureThesis(TimestampedModel):
mandate = models.ForeignKey(CompanyMandate, on_delete=models.CASCADE, related_name="theses")
title = models.CharField(max_length=255)
thesis = models.TextField()
similarity_fingerprint = models.CharField(max_length=128, blank=True)
related_theses = models.JSONField(default=list, blank=True)
competitive_theses = models.JSONField(default=list, blank=True)
portfolio_visibility = models.JSONField(default=dict, blank=True)
metadata = models.JSONField(default=dict, blank=True)
class CompanyProposal(TimestampedModel):
mandate = models.ForeignKey(CompanyMandate, on_delete=models.PROTECT, related_name="company_proposals")
thesis = models.ForeignKey(VentureThesis, on_delete=models.SET_NULL, null=True, blank=True, related_name="company_proposals")
title = models.CharField(max_length=255)
description = models.TextField()
problem = models.TextField()
target_customer = models.TextField()
proposed_solution = models.TextField()
business_model = models.TextField()
pricing_hypothesis = models.TextField()
acquisition_strategy = models.TextField()
validation_plan = models.TextField()
capital_requested = models.DecimalField(max_digits=10, decimal_places=2, default=0)
time_to_first_dollar_estimate = models.CharField(max_length=120)
expected_margin = models.CharField(max_length=120)
build_complexity = models.CharField(max_length=80)
market_evidence = models.JSONField(default=list, blank=True)
differentiation = models.TextField()
major_risks = models.JSONField(default=list, blank=True)
confidence = models.FloatField(default=0.0)
status = models.CharField(max_length=32, choices=CompanyProposalStatus.choices, default=CompanyProposalStatus.DRAFT)
pitch = models.JSONField(default=dict, blank=True)
metadata = models.JSONField(default=dict, blank=True)
class CompanyBoardReview(TimestampedModel):
proposal = models.ForeignKey(CompanyProposal, on_delete=models.CASCADE, related_name="board_reviews")
observations = models.JSONField(default=dict, blank=True)
strengths = models.JSONField(default=list, blank=True)
weaknesses = models.JSONField(default=list, blank=True)
key_assumptions = models.JSONField(default=list, blank=True)
required_revisions = models.JSONField(default=list, blank=True)
recommendation = models.CharField(max_length=80)
revised_pitch = models.JSONField(default=dict, blank=True)
metadata = models.JSONField(default=dict, blank=True)
class ICDiligence(TimestampedModel):
proposal = models.ForeignKey(CompanyProposal, on_delete=models.CASCADE, related_name="ic_diligence")
status = models.CharField(max_length=32, default="INITIAL_PITCH")
rounds = models.JSONField(default=list, blank=True)
red_team_challenge = models.JSONField(default=dict, blank=True)
final_response = models.JSONField(default=dict, blank=True)
metadata = models.JSONField(default=dict, blank=True)
class ICQuestion(TimestampedModel):
diligence = models.ForeignKey(ICDiligence, on_delete=models.CASCADE, related_name="questions")
question = models.TextField()
category = models.CharField(max_length=80)
evidence_required = models.BooleanField(default=True)
round_name = models.CharField(max_length=80, default="Diligence Round 1")
metadata = models.JSONField(default=dict, blank=True)
class ICResponse(TimestampedModel):
question = models.ForeignKey(ICQuestion, on_delete=models.CASCADE, related_name="responses")
answer = models.TextField()
evidence = models.JSONField(default=list, blank=True)
uncertainty = models.TextField(blank=True)
pitch_changes = models.JSONField(default=dict, blank=True)
metadata = models.JSONField(default=dict, blank=True)
class ICDecision(TimestampedModel):
diligence = models.OneToOneField(ICDiligence, on_delete=models.CASCADE, related_name="decision")
decision = models.CharField(max_length=32, choices=ICDecisionType.choices)
component_scores = models.JSONField(default=dict, blank=True)
composite_score = models.FloatField(default=0.0)
probability_500_within_30_days = models.FloatField(default=0.0)
initial_tranche = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
validation_condition = models.TextField(blank=True)
evidence_required = models.JSONField(default=list, blank=True)
recommended_allocation = models.JSONField(default=dict, blank=True)
kill_criteria = models.JSONField(default=list, blank=True)
next_decision_point = models.TextField(blank=True)
metadata = models.JSONField(default=dict, blank=True)
class CompanyCapabilityRequirement(TimestampedModel):
proposal = models.ForeignKey(CompanyProposal, on_delete=models.CASCADE, related_name="capability_requirements")
category = models.CharField(max_length=120)
status = models.CharField(max_length=32, choices=CapabilityStatus.choices)
rationale = models.TextField(blank=True)
priority = models.CharField(max_length=32, choices=CapabilityPriority.choices, default=CapabilityPriority.BEFORE_SCALING)
evidence = models.JSONField(default=dict, blank=True)
class PortfolioCapabilityGap(TimestampedModel):
proposal = models.ForeignKey(CompanyProposal, on_delete=models.CASCADE, related_name="capability_gap_reports")
available = models.JSONField(default=list, blank=True)
partial = models.JSONField(default=list, blank=True)
missing = models.JSONField(default=list, blank=True)
ranked_missing = models.JSONField(default=list, blank=True)
report = models.TextField(blank=True)
metadata = models.JSONField(default=dict, blank=True)
class VentureArtifact(TimestampedModel):
proposal = models.ForeignKey(CompanyProposal, on_delete=models.CASCADE, null=True, blank=True, related_name="artifacts")
mandate = models.ForeignKey(CompanyMandate, on_delete=models.CASCADE, null=True, blank=True, related_name="artifacts")
graph_run = models.ForeignKey("graph.GraphRun", on_delete=models.SET_NULL, null=True, blank=True, related_name="venture_artifacts")
artifact_type = models.CharField(max_length=80)
name = models.CharField(max_length=255)
content = models.JSONField(default=dict, blank=True)
readable = models.TextField(blank=True)
generated_by = models.CharField(max_length=120, blank=True)