Receber por email
← Voltar para o catálogo

budget-variance-analyzer

Analyze construction budget variances. Compare estimated vs actual costs, identify trends, forecast final costs, and generate variance reports for cost control.

190estrelas
Atualizado há 8 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/budget-variance-analyzer-datadrivenconstruction/svg)](https://www.skillteca.com.br/skills/budget-variance-analyzer-datadrivenconstruction)
#ai

Skills relacionadas

Ver todas de Documentos →

Alerta por categoria

Receba novas skills de Documentos toda segunda

1 email curto, só com as skills novas de Documentos. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Budget Variance Analyzer

Overview

Analyze construction budget variances between estimated and actual costs. Track cost performance by category, identify concerning trends, forecast final costs, and provide actionable insights for cost control.

Variance Analysis Framework

┌─────────────────────────────────────────────────────────────────┐
│                  BUDGET VARIANCE ANALYSIS                        │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Budget    vs    Actual    =    Variance    →    Forecast      │
│  ──────         ──────          ────────         ────────       │
│  📋 Original    💰 Spent        📊 Over/Under    🔮 EAC         │
│  📝 Revised     📈 Committed    📉 Trend         📋 ETC         │
│  🎯 Baseline    🧾 Invoiced     ⚠️ Alerts        📊 VAC         │
│                                                                  │
│  EAC = Estimate at Completion                                   │
│  ETC = Estimate to Complete                                     │
│  VAC = Variance at Completion                                   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Technical Implementation

from dataclasses import dataclass, field
from typing import List, Dict, Optional, Tuple
from datetime import datetime, timedelta
from enum import Enum
import statistics

class CostCategory(Enum):
    LABOR = "labor"
    MATERIALS = "materials"
    EQUIPMENT = "equipment"
    SUBCONTRACTOR = "subcontractor"
    GENERAL_CONDITIONS = "general_conditions"
    OVERHEAD = "overhead"
    CONTINGENCY = "contingency"
    FEE = "fee"

class VarianceStatus(Enum):
    ON_BUDGET = "on_budget"
    UNDER_BUDGET = "under_budget"
    OVER_BUDGET = "over_budget"
    CRITICAL = "critical"

@dataclass
class CostCode:
    code: str
    description: str
    category: CostCategory
    original_budget: float
    revised_budget: float = 0.0
    committed: float = 0.0
    actual: float = 0.0
    forecast: float = 0.0
    percent_complete: float = 0.0

    @property
    def budget(self) -> float:
        return self.revised_budget if self.revised_budget else self.original_budget

    @property
    def variance(self) -> float:
        return self.budget - self.actual

    @property
    def variance_percent(self) -> float:
        return (self.variance / self.budget * 100) if self.budget else 0

    @property
    def committed_variance(self) -> float:
        return self.budget - self.committed

    @property
    def estimate_to_complete(self) -> float:
        if self.percent_complete >= 100:
            return 0
        return self.forecast - self.actual

    @property
    def variance_at_completion(self) -> float:
        return self.budget - self.forecast

@dataclass
class CostSnapshot:
    date: datetime
    cost_code: str
    actual: float
    committed: float
    forecast: float

@dataclass
class VarianceReport:
    report_date: datetime
    project_name: str
    total_budget: float
    total_actual: float
    total_committed: float
    total_forecast: float
    variance: float
    variance_percent: float
    eac: float
    etc: float
    vac: float
    variances_by_category: Dict[str, Dict]
    critical_items: List[CostCode]
    trend: str

class BudgetVarianceAnalyzer:
    """Analyze construction budget variances."""

    # Thresholds for variance status
    VARIANCE_THRESHOLDS = {
        "under_budget": 0.05,   # 5% under
        "on_budget": 0.00,
        "over_budget": -0.05,  # 5% over
        "critical": -0.10      # 10% over
    }

    def __init__(self, project_name: str, original_budget: float):
        self.project_name = project_name
        self.original_budget = original_budget
        self.cost_codes: Dict[str, CostCode] = {}
        self.snapshots: List[CostSnapshot] = []
        self.contingency_used = 0.0

    def add_cost_code(self, code: str, description: str,
                     category: CostCategory, budget: float) -> CostCode:
        """Add cost code to budget."""
        cost_code = CostCode(
            code=code,
            description=description,
            category=category,
            original_budget=budget,
            revised_budget=budget,
            forecast=budget
        )
        self.cost_codes[code] = cost_code
        return cost_code

    def import_budget(self, items: List[Dict]) -> int:
        """Import budget from list of items."""
        count = 0
        for item in items:
            self.add_cost_code(
                item['code'],
                item['description'],
                CostCategory(item.get('category', 'other')),
                item['budget']
            )
            count += 1
        return count

    def update_actual(self, code: str, actual: float) -> CostCode:
        """Update actual cost for cost code."""
        if code not in self.cost_codes:
            raise ValueError(f"Cost code {code} not found")

        cost_code = self.cost_codes[code]
        cost_code.actual = actual

        # Record snapshot
        self._record_snapshot(code)

        return cost_code

    def update_committed(self, code: str, committed: float) -> CostCode:
        """Update committed cost (contracts, POs)."""
        if code not in self.cost_codes:
            raise ValueError(f"Cost code {code} not found")

        cost_code = self.cost_codes[code]
        cost_code.committed = committed

        # Update forecast if committed exceeds current forecast
        if committed > cost_code.forecast:
            cost_code.forecast = committed

        self._record_snapshot(code)
        return cost_code

    def update_forecast(self, code: str, forecast: float,
                       percent_complete: float = None) -> CostCode:
        """Update forecast for cost code."""
        if code not in self.cost_codes:
            raise ValueError(f"Cost code {code} not found")

        cost_code = self.cost_codes[code]
        cost_code.forecast = forecast

        if percent_complete is not None:
            cost_code.percent_complete = percent_complete

        self._record_snapshot(code)
        return cost_code

    def revise_budget(self, code: str, new_budget: float,
                     reason: str = "") -> CostCode:
        """Revise budget for cost code."""
        if code not in self.cost_codes:
            raise ValueError(f"Cost code {code} not found")

        cost_code = self.cost_codes[code]
        cost_code.revised_budget = new_budget
        cost_code.forecast = new_budget

        return cost_code

    def use_contingency(self, amount: float, target_code: str,
                       reason: str = "") -> float:
        """Use contingency to cover variance."""
        self.contingency_used += amount

        if target_code in self.cost_codes:
            cc = self.cost_codes[target_code]
            cc.revised_budget += amount

        return self.contingency_used

    def _record_snapshot(self, code: str):
        """Record cost snapshot for trending."""
        if code not in self.cost_codes:
            return

        cc = self.cost_codes[code]
        snapshot = CostSnapshot(
            date=datetime.now(),
            cost_code=code,
            actual=cc.actual,
            committed=cc.committed,
            forecast=cc.forecast
        )
        self.snapshots.append(snapshot)

    def get_variance_status(self, variance_percent: float) -> VarianceStatus:
        """Determine variance status."""
        if variance_percent >= self.VARIANCE_THRESHOLDS["under_budget"]:
            return VarianceStatus.UNDER_BUDGET
        elif variance_percent >= self.VARIANCE_THRESHOLDS["over_budget"]:
            return VarianceStatus.ON_BUDGET
        elif variance_percent >= self.VARIANCE_THRESHOLDS["critical"]:
            return VarianceStatus.OVER_BUDGET
        else:
        
Compartilhar X LinkedIn