warranty-tracker

Track and manage construction warranties. Monitor expiration dates, claims, and manufacturer documentation.

Works with

Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: warranty-tracker
description: Track and manage construction warranties. Monitor expiration dates, claims, and manufacturer documentation.
license: MIT
---

# Warranty Tracker

## Business Case

### Problem Statement
Warranty management is often neglected:
- Missing warranty documentation
- Expired warranties untracked
- Difficult to file claims
- Scattered across multiple files

### Solution
Centralized warranty tracking system that monitors expiration dates, stores documentation, and manages claims.

### Business Value
- **Cost savings** - File claims before expiration
- **Organization** - Central warranty repository
- **Compliance** - Meet handover requirements
- **Proactive** - Automatic expiration alerts

## 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 WarrantyType(Enum):
    """Types of warranties."""
    MANUFACTURER = "manufacturer"
    CONTRACTOR = "contractor"
    INSTALLER = "installer"
    EXTENDED = "extended"
    PERFORMANCE = "performance"


class WarrantyStatus(Enum):
    """Warranty status."""
    ACTIVE = "active"
    EXPIRING_SOON = "expiring_soon"  # Within 90 days
    EXPIRED = "expired"
    CLAIMED = "claimed"
    VOID = "void"


class ClaimStatus(Enum):
    """Warranty claim status."""
    DRAFT = "draft"
    SUBMITTED = "submitted"
    UNDER_REVIEW = "under_review"
    APPROVED = "approved"
    DENIED = "denied"
    RESOLVED = "resolved"


class BuildingSystem(Enum):
    """Building systems."""
    STRUCTURAL = "structural"
    ROOFING = "roofing"
    HVAC = "hvac"
    ELECTRICAL = "electrical"
    PLUMBING = "plumbing"
    ELEVATORS = "elevators"
    FIRE_PROTECTION = "fire_protection"
    GLAZING = "glazing"
    FLOORING = "flooring"
    PAINTING = "painting"
    APPLIANCES = "appliances"
    EXTERIOR = "exterior"
    OTHER = "other"


@dataclass
class WarrantyDocument:
    """Warranty document reference."""
    document_id: str
    filename: str
    document_type: str  # certificate, manual, conditions
    upload_date: date
    file_path: str


@dataclass
class Warranty:
    """Warranty record."""
    warranty_id: str
    item_description: str
    system: BuildingSystem
    warranty_type: WarrantyType
    manufacturer: str
    contractor: str
    start_date: date
    end_date: date
    duration_years: int
    coverage_details: str
    exclusions: str
    contact_name: str
    contact_phone: str
    contact_email: str
    location: str
    documents: List[WarrantyDocument] = field(default_factory=list)
    notes: str = ""

    @property
    def status(self) -> WarrantyStatus:
        """Calculate current warranty status."""
        today = date.today()
        if today > self.end_date:
            return WarrantyStatus.EXPIRED
        elif (self.end_date - today).days <= 90:
            return WarrantyStatus.EXPIRING_SOON
        else:
            return WarrantyStatus.ACTIVE

    @property
    def days_remaining(self) -> int:
        """Days until warranty expires."""
        return (self.end_date - date.today()).days

    def to_dict(self) -> Dict[str, Any]:
        return {
            'warranty_id': self.warranty_id,
            'item': self.item_description,
            'system': self.system.value,
            'type': self.warranty_type.value,
            'manufacturer': self.manufacturer,
            'contractor': self.contractor,
            'start_date': self.start_date.isoformat(),
            'end_date': self.end_date.isoformat(),
            'duration_years': self.duration_years,
            'status': self.status.value,
            'days_remaining': self.days_remaining,
            'contact': self.contact_email
        }


@dataclass
class WarrantyClaim:
    """Warranty claim record."""
    claim_id: str
    warranty_id: str
    issue_description: str
    issue_date: date
    reported_date: date
    status: ClaimStatus
    reported_by: str
    resolution: str = ""
    resolution_date: Optional[date] = None
    cost_covered: float = 0.0
    documents: List[str] = field(default_factory=list)
    notes: str = ""


class WarrantyTracker:
    """Track and manage construction warranties."""

    EXPIRING_THRESHOLD_DAYS = 90

    def __init__(self, project_name: str, substantial_completion_date: date):
        self.project_name = project_name
        self.completion_date = substantial_completion_date
        self.warranties: Dict[str, Warranty] = {}
        self.claims: Dict[str, WarrantyClaim] = {}
        self._warranty_counter = 0
        self._claim_counter = 0

    def add_warranty(self,
                    item_description: str,
                    system: BuildingSystem,
                    warranty_type: WarrantyType,
                    manufacturer: str,
                    contractor: str,
                    duration_years: int,
                    coverage_details: str,
                    contact_email: str,
                    start_date: date = None,
                    contact_name: str = "",
                    contact_phone: str = "",
                    exclusions: str = "",
                    location: str = "") -> Warranty:
        """Add new warranty record."""
        self._warranty_counter += 1
        warranty_id = f"WRT-{self._warranty_counter:04d}"

        start = start_date or self.completion_date
        end = start + timedelta(days=duration_years * 365)

        warranty = Warranty(
            warranty_id=warranty_id,
            item_description=item_description,
            system=system,
            warranty_type=warranty_type,
            manufacturer=manufacturer,
            contractor=contractor,
            start_date=start,
            end_date=end,
            duration_years=duration_years,
            coverage_details=coverage_details,
            exclusions=exclusions,
            contact_name=contact_name,
            contact_phone=contact_phone,
            contact_email=contact_email,
            location=location
        )

        self.warranties[warranty_id] = warranty
        return warranty

    def add_document(self, warranty_id: str,
                    filename: str,
                    document_type: str,
                    file_path: str) -> WarrantyDocument:
        """Add document to warranty."""
        if warranty_id not in self.warranties:
            raise ValueError(f"Warranty {warranty_id} not found")

        doc_id = f"{warranty_id}-DOC-{len(self.warranties[warranty_id].documents) + 1:02d}"
        document = WarrantyDocument(
            document_id=doc_id,
            filename=filename,
            document_type=document_type,
            upload_date=date.today(),
            file_path=file_path
        )

        self.warranties[warranty_id].documents.append(document)
        return document

    def file_claim(self,
                  warranty_id: str,
                  issue_description: str,
                  issue_date: date,
                  reported_by: str) -> WarrantyClaim:
        """File warranty claim."""
        if warranty_id not in self.warranties:
            raise ValueError(f"Warranty {warranty_id} not found")

        warranty = self.warranties[warranty_id]

        # Check if warranty is active
        if warranty.status == WarrantyStatus.EXPIRED:
            raise ValueError(f"Warranty {warranty_id} has expired")

        self._claim_counter += 1
        claim_id = f"CLM-{self._claim_counter:04d}"

        claim = WarrantyClaim(
            claim_id=claim_id,
            warranty_id=warranty_id,
            issue_description=issue_description,
            issue_date=issue_date,
            reported_date=date.today(),
            status=ClaimStatus.DRAFT,
            reported_by=reported_by
        )

        self.claims[claim_id] = claim
        return claim

    def update_claim_status(self, claim_id: str,
                           status: ClaimStatus,
                           resolution: str = "",
                           cost_covered: float = 0.0):
        """Update claim status."""
        if claim_id not in self.claims:
            raise ValueError(f"Claim {claim_id} not found")

        claim = self.claims[claim_id]
        claim.status = status

        if resolution:
            claim.resolution = resolution

        if cost_covered > 0:
            claim.cost_covered = cost_covered

        if status in [ClaimStatus.APPROVED, ClaimStatus.DENIED, ClaimStatus.RESOLVED]:
            claim.resolution_date = date.today()

    def get_expiring_warranties(self, days: int = None) -> List[Warranty]:
        """Get warranties expiring within specified days."""
        threshold = days or self.EXPIRING_THRESHOLD_DAYS
        cutoff = date.today() + timedelta(days=threshold)

        return [w for w in self.warranties.values()
                if w.status == WarrantyStatus.ACTIVE and w.end_date <= cutoff]

    def get_active_warranties(self) -> List[Warranty]:
        """Get all active warranties."""
        return [w for w in self.warranties.values()
                if w.status in [WarrantyStatus.ACTIVE, WarrantyStatus.EXPIRING_SOON]]

    def get_warranties_by_system(self, system: BuildingSystem) -> List[Warranty]:
        """Get warranties for specific building system."""
        return [w for w in self.warranties.values() if w.system == system]

    def get_summary(self) -> Dict[str, Any]:
        """Generate warranty summary."""
        by_status = {}
        by_system = {}

        for warranty in self.warranties.values():
            # By status
            status = warranty.status.value
            by_status[status] = by_status.get(status, 0) + 1

            # By system
            system = warranty.system.value
            by_system[system] = by_system.get(system, 0) + 1

        # Claims summary
        open_claims = sum(1 for c in self.claims.values()
                        if c.status not in [ClaimStatus.RESOLVED, ClaimStatus.DENIED])
        total_covered = sum(c.cost_covered for c in self.claims.values()
                          if c.status == ClaimStatus.RESOLVED)

        return {
            'total_warranties': len(self.warranties),
            'by_status': by_status,
            'by_system': by_system,
            'expiring_soon': len(self.get_expiring_warranties()),
            'total_claims': len(self.claims),
            'open_claims': open_claims,
            'total_cost_recovered': total_covered,
            'project': self.project_name,
            'completion_date': self.completion_date.isoformat()
        }

    def generate_expiration_report(self, months_ahead: int = 12) -> pd.DataFrame:
        """Generate warranty expiration report."""
        cutoff = date.today() + timedelta(days=months_ahead * 30)
        upcoming = [w for w in self.warranties.values() if w.end_date <= cutoff]

        data = []
        for w in sorted(upcoming, key=lambda x: x.end_date):
            data.append({
                'Warranty ID': w.warranty_id,
                'Item': w.item_description,
                'System': w.system.value,
                'Manufacturer': w.manufacturer,
                'End Date': w.end_date,
                'Days Remaining': w.days_remaining,
                'Status': w.status.value,
                'Contact': w.contact_email
            })

        return pd.DataFrame(data)

    def export_to_excel(self, output_path: str):
        """Export all warranty data to Excel."""
        with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
            # Warranties
            warranties_df = pd.DataFrame([w.to_dict() for w in self.warranties.values()])
            if not warranties_df.empty:
                warranties_df.to_excel(writer, sheet_name='Warranties', index=False)

            # Claims
            claims_data = []
            for claim in self.claims.values():
                warranty = self.warranties.get(claim.warranty_id)
                claims_data.append({
                    'Claim ID': claim.claim_id,
                    'Warranty ID': claim.warranty_id,
                    'Item': warranty.item_description if warranty else '',
                    'Issue': claim.issue_description,
                    'Issue Date': claim.issue_date,
                    'Status': claim.status.value,
                    'Resolution': claim.resolution,
                    'Cost Covered': claim.cost_covered
                })

            if claims_data:
                pd.DataFrame(claims_data).to_excel(writer, sheet_name='Claims', index=False)

            # Expiring soon
            expiring = self.generate_expiration_report(6)
            if not expiring.empty:
                expiring.to_excel(writer, sheet_name='Expiring Soon', index=False)

        return output_path
```

## Quick Start

```python
from datetime import date

# Initialize tracker
tracker = WarrantyTracker(
    project_name="Office Tower",
    substantial_completion_date=date(2024, 6, 1)
)

# Add warranties
tracker.add_warranty(
    item_description="HVAC System - Rooftop Units",
    system=BuildingSystem.HVAC,
    warranty_type=WarrantyType.MANUFACTURER,
    manufacturer="Carrier",
    contractor="ABC Mechanical",
    duration_years=5,
    coverage_details="Parts and labor for manufacturing defects",
    contact_email="warranty@carrier.com"
)

# Check expiring warranties
expiring = tracker.get_expiring_warranties(90)
print(f"Warranties expiring in 90 days: {len(expiring)}")
```

## Common Use Cases

### 1. Monthly Review
```python
# Get expiration report
report = tracker.generate_expiration_report(months_ahead=3)
print(report[['Item', 'End Date', 'Days Remaining']])
```

### 2. File Claim
```python
claim = tracker.file_claim(
    warranty_id="WRT-0001",
    issue_description="RTU-1 compressor failure",
    issue_date=date.today(),
    reported_by="Building Manager"
)
```

### 3. Export for Handover
```python
tracker.export_to_excel("warranty_register.xlsx")
```

## Resources
- **DDC Book**: Chapter 5 - Project Closeout
- **Reference**: AIA Document G714

More Writing & Documentation skills

paper-context-resolver

lllllllama/rigorpilot-skills

Rigor Paper Context helper for README-first deep learning repo reproduction. Use only when the README and repository files leave a narrow reproduction-critical gap and the task is to resolve a specific paper detail such as dataset split, preprocessing, evaluation protocol, checkpoint mapping, or runtime assumption from primary paper sources while recording conflicts. Do not use for general paper summary, repo scanning, environment setup, command execution, title-only paper lookup, or replacing README guidance by default.

450.8k

repo-intake-and-plan

lllllllama/rigorpilot-skills

Rigor Intake helper for README-first deep learning repo reproduction. Use when the task is specifically to scan a repository, read the README and common project files, extract documented commands, classify inference, evaluation, and training candidates, and return the smallest trustworthy reproduction plan to the main orchestrator. Do not use for environment setup, asset download, command execution, final reporting, paper lookup, or end-to-end orchestration.

450.0k

minimal-run-and-audit

lllllllama/rigorpilot-skills

Rigor Run skill for README-first deep learning repo reproduction. Use when the task is specifically to capture or normalize evidence from the selected smoke test or documented inference or evaluation command and write standardized `repro_outputs/` files, including patch notes when repository files changed. Do not use for training execution, initial repo intake, generic environment setup, paper lookup, target selection, hidden scientific-meaning changes, or end-to-end orchestration by itself.

449.9k

← All Writing & Documentation skills

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY