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)