Receber por email
← Voltar para o catálogo

lien-waiver-tracker

Track and manage construction lien waivers. Monitor conditional and unconditional waivers, ensure compliance before payments, and prevent lien exposure.

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/lien-waiver-tracker/svg)](https://www.skillteca.com.br/skills/lien-waiver-tracker)
#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

Lien Waiver Tracker

Overview

Track and manage lien waivers throughout the construction payment process. Ensure proper waivers are received before releasing payments, monitor waiver status by subcontractor, and minimize lien exposure.

Lien Waiver Types

┌─────────────────────────────────────────────────────────────────┐
│                    LIEN WAIVER TYPES                             │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  CONDITIONAL                        UNCONDITIONAL                │
│  ───────────                        ─────────────                │
│  📋 Progress - Conditional          ✅ Progress - Unconditional  │
│     Effective when paid                Immediately effective     │
│     Use with payment                   Use after check clears    │
│                                                                  │
│  📋 Final - Conditional             ✅ Final - Unconditional     │
│     For final payment                  For final payment         │
│     Upon receipt of funds              After funds received      │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Technical Implementation

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

class WaiverType(Enum):
    CONDITIONAL_PROGRESS = "conditional_progress"
    UNCONDITIONAL_PROGRESS = "unconditional_progress"
    CONDITIONAL_FINAL = "conditional_final"
    UNCONDITIONAL_FINAL = "unconditional_final"

class WaiverStatus(Enum):
    REQUESTED = "requested"
    RECEIVED = "received"
    VERIFIED = "verified"
    REJECTED = "rejected"
    MISSING = "missing"

class PaymentStatus(Enum):
    PENDING = "pending"
    APPROVED = "approved"
    HELD = "held"
    RELEASED = "released"

@dataclass
class Subcontractor:
    id: str
    name: str
    trade: str
    contract_amount: float
    contact_name: str
    contact_email: str
    tier: int = 1  # 1 = direct, 2 = sub-sub

@dataclass
class LienWaiver:
    id: str
    subcontractor_id: str
    waiver_type: WaiverType
    payment_application: int  # Pay app number
    through_date: datetime
    amount: float
    status: WaiverStatus = WaiverStatus.REQUESTED
    requested_date: datetime = field(default_factory=datetime.now)
    received_date: Optional[datetime] = None
    verified_by: str = ""
    file_path: str = ""
    notes: str = ""

@dataclass
class PaymentApplication:
    number: int
    period_end: datetime
    subcontractor_id: str
    amount_requested: float
    amount_approved: float
    retainage: float
    status: PaymentStatus = PaymentStatus.PENDING
    waivers_complete: bool = False
    payment_date: Optional[datetime] = None

@dataclass
class LienExposure:
    subcontractor_id: str
    subcontractor_name: str
    total_paid: float
    unconditional_waivers: float
    conditional_pending: float
    exposure: float

class LienWaiverTracker:
    """Track and manage construction lien waivers."""

    def __init__(self, project_id: str, project_name: str):
        self.project_id = project_id
        self.project_name = project_name
        self.subcontractors: Dict[str, Subcontractor] = {}
        self.waivers: Dict[str, LienWaiver] = {}
        self.pay_apps: Dict[str, PaymentApplication] = {}

    def add_subcontractor(self, id: str, name: str, trade: str,
                         contract_amount: float, contact_name: str,
                         contact_email: str, tier: int = 1) -> Subcontractor:
        """Add subcontractor to tracking."""
        sub = Subcontractor(
            id=id,
            name=name,
            trade=trade,
            contract_amount=contract_amount,
            contact_name=contact_name,
            contact_email=contact_email,
            tier=tier
        )
        self.subcontractors[id] = sub
        return sub

    def create_payment_application(self, number: int, period_end: datetime,
                                  subcontractor_id: str, amount_requested: float,
                                  retainage_rate: float = 0.10) -> PaymentApplication:
        """Create payment application record."""
        if subcontractor_id not in self.subcontractors:
            raise ValueError(f"Subcontractor {subcontractor_id} not found")

        retainage = amount_requested * retainage_rate
        amount_approved = amount_requested - retainage

        pay_app = PaymentApplication(
            number=number,
            period_end=period_end,
            subcontractor_id=subcontractor_id,
            amount_requested=amount_requested,
            amount_approved=amount_approved,
            retainage=retainage
        )

        key = f"{subcontractor_id}-{number}"
        self.pay_apps[key] = pay_app

        # Create waiver request
        self.request_waiver(subcontractor_id, number, period_end, amount_approved)

        return pay_app

    def request_waiver(self, subcontractor_id: str, pay_app_number: int,
                      through_date: datetime, amount: float,
                      waiver_type: WaiverType = WaiverType.CONDITIONAL_PROGRESS) -> LienWaiver:
        """Request lien waiver from subcontractor."""
        waiver_id = f"LW-{subcontractor_id}-{pay_app_number}"

        waiver = LienWaiver(
            id=waiver_id,
            subcontractor_id=subcontractor_id,
            waiver_type=waiver_type,
            payment_application=pay_app_number,
            through_date=through_date,
            amount=amount
        )

        self.waivers[waiver_id] = waiver
        return waiver

    def receive_waiver(self, waiver_id: str, file_path: str,
                      verified_by: str = "") -> LienWaiver:
        """Record receipt of lien waiver."""
        if waiver_id not in self.waivers:
            raise ValueError(f"Waiver {waiver_id} not found")

        waiver = self.waivers[waiver_id]
        waiver.status = WaiverStatus.RECEIVED
        waiver.received_date = datetime.now()
        waiver.file_path = file_path
        waiver.verified_by = verified_by

        # Check if all waivers for pay app complete
        self._check_pay_app_waivers(waiver.subcontractor_id, waiver.payment_application)

        return waiver

    def verify_waiver(self, waiver_id: str, verified_by: str) -> LienWaiver:
        """Verify waiver details are correct."""
        if waiver_id not in self.waivers:
            raise ValueError(f"Waiver {waiver_id} not found")

        waiver = self.waivers[waiver_id]
        waiver.status = WaiverStatus.VERIFIED
        waiver.verified_by = verified_by

        return waiver

    def reject_waiver(self, waiver_id: str, reason: str) -> LienWaiver:
        """Reject waiver (incorrect amount, wrong form, etc.)."""
        if waiver_id not in self.waivers:
            raise ValueError(f"Waiver {waiver_id} not found")

        waiver = self.waivers[waiver_id]
        waiver.status = WaiverStatus.REJECTED
        waiver.notes = f"Rejected: {reason}"

        return waiver

    def convert_to_unconditional(self, waiver_id: str, payment_date: datetime) -> LienWaiver:
        """Convert conditional waiver to unconditional after payment clears."""
        if waiver_id not in self.waivers:
            raise ValueError(f"Waiver {waiver_id} not found")

        waiver = self.waivers[waiver_id]

        # Create new unconditional waiver
        new_type = (WaiverType.UNCONDITIONAL_PROGRESS
                   if waiver.waiver_type == WaiverType.CONDITIONAL_PROGRESS
                   else WaiverType.UNCONDITIONAL_FINAL)

        return self.request_waiver(
            waiver.subcontractor_id,
            waiver.payment_application,
            waiver.through_date,
            waiver.amount,
            new_type
        )

    def _check_pay_app_waivers(self, subcontract
Compartilhar X LinkedIn