submittal-tracker
The submittal-tracker skill manages construction project submittals throughout their complete lifecycle, tracking status from draft through approval stages including under review, approved, approved as noted, revise resubmit, and rejected states. Use this skill to coordinate submittal workflows across multiple contractors, maintain revision histories, record reviewer comments and compliance notes, and monitor submission deadlines to prevent project delays.
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction /tmp/submittal-tracker && cp -r /tmp/submittal-tracker/1_DDC_Toolkit/Document-Control/submittal-tracker ~/.claude/skills/submittal-trackerSKILL.md
# Submittal Tracker
## Business Case
Submittals require careful tracking to avoid delays. This skill manages the entire submittal workflow from creation to approval.
## Technical Implementation
```python
import pandas as pd
from datetime import datetime, date, timedelta
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from enum import Enum
class SubmittalStatus(Enum):
DRAFT = "draft"
SUBMITTED = "submitted"
UNDER_REVIEW = "under_review"
APPROVED = "approved"
APPROVED_AS_NOTED = "approved_as_noted"
REVISE_RESUBMIT = "revise_resubmit"
REJECTED = "rejected"
class SubmittalType(Enum):
PRODUCT_DATA = "product_data"
SHOP_DRAWING = "shop_drawing"
SAMPLE = "sample"
MOCK_UP = "mock_up"
CERTIFICATE = "certificate"
TEST_REPORT = "test_report"
@dataclass
class ReviewComment:
reviewer: str
comment: str
comment_date: date
resolved: bool = False
@dataclass
class Submittal:
submittal_id: str
spec_section: str
title: str
submittal_type: SubmittalType
status: SubmittalStatus
contractor: str
revision: int
submitted_date: Optional[date]
required_date: date
approved_date: Optional[date] = None
comments: List[ReviewComment] = field(default_factory=list)
files: List[str] = field(default_factory=list)
class SubmittalTracker:
def __init__(self, project_name: str):
self.project_name = project_name
self.submittals: Dict[str, Submittal] = {}
self._counter = 0
def create_submittal(self, spec_section: str, title: str,
submittal_type: SubmittalType, contractor: str,
required_date: date) -> Submittal:
self._counter += 1
sub_id = f"SUB-{self._counter:04d}"
submittal = Submittal(
submittal_id=sub_id,
spec_section=spec_section,
title=title,
submittal_type=submittal_type,
status=SubmittalStatus.DRAFT,
contractor=contractor,
revision=0,
submitted_date=None,
required_date=required_date
)
self.submittals[sub_id] = submittal
return submittal
def submit(self, sub_id: str, files: List[str]):
if sub_id in self.submittals:
self.submittals[sub_id].status = SubmittalStatus.SUBMITTED
self.submittals[sub_id].submitted_date = date.today()
self.submittals[sub_id].files = files
def review(self, sub_id: str, status: SubmittalStatus, reviewer: str, comment: str = ""):
if sub_id in self.submittals:
sub = self.submittals[sub_id]
sub.status = status
if comment:
sub.comments.append(ReviewComment(reviewer, comment, date.today()))
if status in [SubmittalStatus.APPROVED, SubmittalStatus.APPROVED_AS_NOTED]:
sub.approved_date = date.today()
def resubmit(self, sub_id: str, files: List[str]):
if sub_id in self.submittals:
sub = self.submittals[sub_id]
sub.revision += 1
sub.status = SubmittalStatus.SUBMITTED
sub.submitted_date = date.today()
sub.files = files
def get_pending(self) -> List[Submittal]:
return [s for s in self.submittals.values()
if s.status in [SubmittalStatus.SUBMITTED, SubmittalStatus.UNDER_REVIEW]]
def get_overdue(self) -> List[Submittal]:
today = date.today()
return [s for s in self.submittals.values()
if s.status not in [SubmittalStatus.APPROVED, SubmittalStatus.APPROVED_AS_NOTED]
and s.required_date < today]
def export_log(self, output_path: str):
data = [{
'ID': s.submittal_id,
'Spec': s.spec_section,
'Title': s.title,
'Type': s.submittal_type.value,
'Status': s.status.value,
'Rev': s.revision,
'Submitted': s.submitted_date,
'Required': s.required_date,
'Approved': s.approved_date
} for s in self.submittals.values()]
pd.DataFrame(data).to_excel(output_path, index=False)
```
## Quick Start
```python
tracker = SubmittalTracker("Office Tower")
sub = tracker.create_submittal("09 29 00", "Gypsum Board",
SubmittalType.PRODUCT_DATA, "ABC Drywall",
date.today() + timedelta(days=14))
tracker.submit(sub.submittal_id, ["spec_sheet.pdf"])
tracker.review(sub.submittal_id, SubmittalStatus.APPROVED, "Architect")
```
## Resources
- **DDC Book**: Chapter 4 - Document ControlAnalyze 5000+ IFC and Revit projects at scale for patterns, benchmarks, and insights. Big data analysis for construction.
Manage as-built documentation for project closeout. Track drawing markups, coordinate updates, and verify completeness.
Track as-built documentation and record drawings. Monitor submission status, manage revisions, and ensure completeness for handover.
Batch convert multiple CAD/BIM files (Revit, IFC, DWG, DGN) with progress tracking, error handling, and consolidated reporting.
Compare and analyze contractor bids. Score proposals, identify scope gaps, and recommend selections.
Detect and analyze geometric clashes in BIM models. Identify MEP, structural, and architectural conflicts before construction.
Classify BIM elements using AI and standard classification systems. Map elements to UniFormat, MasterFormat, OmniClass, and CWICR codes.
Automated cost estimation from BIM models using DDC CWICR database (8 national bases, 78,228 positions). AI classification + vector search for accurate pricing.