Iterative Prompting: - Chat box on Match Review tab for natural language refinement - "re-run under 70%" / "ignore zero volume" / "set all volumes to 1" - Claude interprets instruction into structured actions - Actions: rematch_below_threshold, rematch_specific, delete_assets, set_volume - Re-matches affected assets automatically after refinement - Chat log shows instruction history RFP/Brief Analysis: - New "Brief Analysis" tab between Upload and Match Review - Extracts: summary, objectives, KPIs, channels, audiences, deliverable categories, constraints, timeline, budget, complexity assessment - Generates prioritized discovery questions (Red/Amber/Green) - Questions include category, rationale, and priority level - Stored as JSON in project.brief_analysis field - Uploaded files now saved to data dir for re-analysis - Re-analyze button to refresh analysis Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
115 lines
2.4 KiB
Python
115 lines
2.4 KiB
Python
from pydantic import BaseModel
|
|
from datetime import datetime
|
|
|
|
|
|
class ProjectCreate(BaseModel):
|
|
name: str
|
|
client_name: str | None = None
|
|
description: str | None = None
|
|
model_type: str = "current_oplus"
|
|
|
|
|
|
class ProjectUpdate(BaseModel):
|
|
name: str | None = None
|
|
client_name: str | None = None
|
|
description: str | None = None
|
|
model_type: str | None = None
|
|
|
|
|
|
class ProjectOut(BaseModel):
|
|
id: int
|
|
name: str
|
|
client_name: str | None
|
|
description: str | None
|
|
model_type: str
|
|
status: str
|
|
source_filename: str | None
|
|
parse_stage: str | None = None
|
|
has_brief_analysis: bool = False
|
|
ai_input_tokens: int = 0
|
|
ai_output_tokens: int = 0
|
|
ai_cost_usd: float = 0
|
|
ai_call_count: int = 0
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
asset_count: int = 0
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class ClientAssetOut(BaseModel):
|
|
id: int
|
|
project_id: int
|
|
raw_name: str | None
|
|
raw_description: str | None
|
|
volume: int
|
|
sort_order: int | None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class ClientAssetUpdate(BaseModel):
|
|
raw_name: str | None = None
|
|
raw_description: str | None = None
|
|
volume: int | None = None
|
|
|
|
|
|
class MatchOut(BaseModel):
|
|
id: int
|
|
client_asset_id: int
|
|
gmal_asset_id: int
|
|
gmal_id: str | None = None
|
|
gmal_name: str | None = None
|
|
gmal_unique_name: str | None = None
|
|
confidence: str
|
|
confidence_score: float | None
|
|
ai_reasoning: str | None
|
|
caveat_text: str | None
|
|
is_selected: bool
|
|
rank: int
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class MatchSelectRequest(BaseModel):
|
|
is_selected: bool = True
|
|
|
|
|
|
class ManualMatchRequest(BaseModel):
|
|
gmal_asset_id: int
|
|
|
|
|
|
class RatecardLineOut(BaseModel):
|
|
id: int
|
|
client_asset_id: int
|
|
client_asset_name: str | None = None
|
|
gmal_asset_id: int
|
|
gmal_id: str | None = None
|
|
role_id: int
|
|
role_title: str | None = None
|
|
discipline: str | None = None
|
|
base_hours: float | None
|
|
volume: int
|
|
total_hours: float | None
|
|
manual_override: float | None
|
|
notes: str | None
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
class RatecardLineUpdate(BaseModel):
|
|
manual_override: float | None = None
|
|
notes: str | None = None
|
|
|
|
|
|
class RatecardSummary(BaseModel):
|
|
project_id: int
|
|
project_name: str
|
|
model_type: str
|
|
total_assets: int
|
|
total_hours: float
|
|
lines: list[RatecardLineOut]
|