Skip to main content Skills Marktplatz Entdecken und erkunden Sie KI-Skills, die von der Community erstellt wurden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Prompt kopierenPrompt-Details anzeigen Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
npx skills add https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill lien-waiver-trackerDer Befehl bleibt in einer Zeile. Scrollen Sie horizontal, um ihn vor dem Kopieren vollständig zu prüfen.
Sie bevorzugen eine lokale Kopie? Laden Sie die Dateien herunter, die SkillsMP derzeit vorliegen.
ZIP herunterladen Herunterladen... Mehr aus diesem Repository Verwandte Berufe SOC
Basierend auf der SOC-Berufsklassifikation
name lien-waiver-tracker description Track and manage construction lien waivers. Monitor conditional and unconditional waivers, ensure compliance before payments, and prevent lien exposure. homepage https://datadrivenconstruction.io metadata {"openclaw":{"emoji":"📝","os":["darwin","linux","win32"],"homepage":"https://datadrivenconstruction.io","requires":{"bins":["python3"]}}}
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
@dataclass
:
:
subcontractor_id:
waiver_type: WaiverType
payment_application:
through_date: datetime
amount:
status: WaiverStatus = WaiverStatus.REQUESTED
requested_date: datetime = field(default_factory=datetime.now)
received_date: [datetime] =
verified_by: =
file_path: =
notes: =
:
number:
period_end: datetime
subcontractor_id:
amount_requested:
amount_approved:
retainage:
status: PaymentStatus = PaymentStatus.PENDING
waivers_complete: =
payment_date: [datetime] =
:
subcontractor_id:
subcontractor_name:
total_paid:
unconditional_waivers:
conditional_pending:
exposure:
:
( ):
.project_id = project_id
.project_name = project_name
.subcontractors: [ , Subcontractor] = {}
.waivers: [ , LienWaiver] = {}
.pay_apps: [ , PaymentApplication] = {}
( ) -> Subcontractor:
sub = Subcontractor(
= ,
name=name,
trade=trade,
contract_amount=contract_amount,
contact_name=contact_name,
contact_email=contact_email,
tier=tier
)
.subcontractors[ ] = sub
sub
( ) -> PaymentApplication:
subcontractor_id .subcontractors:
ValueError( )
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 =
.pay_apps[key] = pay_app
.request_waiver(subcontractor_id, number, period_end, amount_approved)
pay_app
( ) -> LienWaiver:
waiver_id =
waiver = LienWaiver(
=waiver_id,
subcontractor_id=subcontractor_id,
waiver_type=waiver_type,
payment_application=pay_app_number,
through_date=through_date,
amount=amount
)
.waivers[waiver_id] = waiver
waiver
( ) -> LienWaiver:
waiver_id .waivers:
ValueError( )
waiver = .waivers[waiver_id]
waiver.status = WaiverStatus.RECEIVED
waiver.received_date = datetime.now()
waiver.file_path = file_path
waiver.verified_by = verified_by
._check_pay_app_waivers(waiver.subcontractor_id, waiver.payment_application)
waiver
( ) -> LienWaiver:
waiver_id .waivers:
ValueError( )
waiver = .waivers[waiver_id]
waiver.status = WaiverStatus.VERIFIED
waiver.verified_by = verified_by
waiver
( ) -> LienWaiver:
waiver_id .waivers:
ValueError( )
waiver = .waivers[waiver_id]
waiver.status = WaiverStatus.REJECTED
waiver.notes =
waiver
( ) -> LienWaiver:
waiver_id .waivers:
ValueError( )
waiver = .waivers[waiver_id]
new_type = (WaiverType.UNCONDITIONAL_PROGRESS
waiver.waiver_type == WaiverType.CONDITIONAL_PROGRESS
WaiverType.UNCONDITIONAL_FINAL)
.request_waiver(
waiver.subcontractor_id,
waiver.payment_application,
waiver.through_date,
waiver.amount,
new_type
)
( ):
key =
key .pay_apps:
pay_app = .pay_apps[key]
related_waivers = [
w w .waivers.values()
w.subcontractor_id == subcontractor_id
w.payment_application == pay_app_number
]
pay_app.waivers_complete = (
w.status [WaiverStatus.RECEIVED, WaiverStatus.VERIFIED]
w related_waivers
)
( ) -> LienExposure:
subcontractor_id .subcontractors:
ValueError( )
sub = .subcontractors[subcontractor_id]
total_paid = (
pa.amount_approved pa .pay_apps.values()
pa.subcontractor_id == subcontractor_id
pa.status == PaymentStatus.RELEASED
)
unconditional = (
w.amount w .waivers.values()
w.subcontractor_id == subcontractor_id
w.waiver_type [WaiverType.UNCONDITIONAL_PROGRESS, WaiverType.UNCONDITIONAL_FINAL]
w.status [WaiverStatus.RECEIVED, WaiverStatus.VERIFIED]
)
conditional = (
w.amount w .waivers.values()
w.subcontractor_id == subcontractor_id
w.waiver_type [WaiverType.CONDITIONAL_PROGRESS, WaiverType.CONDITIONAL_FINAL]
w.status [WaiverStatus.RECEIVED, WaiverStatus.VERIFIED]
)
exposure = total_paid - unconditional
LienExposure(
subcontractor_id=subcontractor_id,
subcontractor_name=sub.name,
total_paid=total_paid,
unconditional_waivers=unconditional,
conditional_pending=conditional,
exposure=exposure
)
( ) -> [ ]:
missing = []
waiver .waivers.values():
waiver.status [WaiverStatus.REQUESTED, WaiverStatus.MISSING]:
sub = .subcontractors.get(waiver.subcontractor_id)
missing.append({
: waiver. ,
: sub.name sub waiver.subcontractor_id,
: waiver.payment_application,
: waiver.amount,
: waiver.waiver_type.value,
: waiver.requested_date,
: (datetime.now() - waiver.requested_date).days
})
(missing, key= x: -x[ ])
( ) -> :
subcontractor_id .subcontractors:
ValueError( )
sub = .subcontractors[subcontractor_id]
waivers = [w w .waivers.values() w.subcontractor_id == subcontractor_id]
by_status = {}
w waivers:
s = w.status.value
by_status[s] = by_status.get(s, ) +
{
: sub.name,
: (waivers),
: by_status,
: (w.amount w waivers),
: (w.amount w waivers w.status == WaiverStatus.VERIFIED)
}
( ) -> :
key =
key .pay_apps:
{ : , : }
pay_app = .pay_apps[key]
waivers = [
w w .waivers.values()
w.subcontractor_id == subcontractor_id
w.payment_application == pay_app_number
w.waiver_type == WaiverType.CONDITIONAL_PROGRESS
]
waivers:
{ : , : }
w waivers:
w.status [WaiverStatus.RECEIVED, WaiverStatus.VERIFIED]:
{ : , : }
{ : , : , : pay_app.amount_approved}
( ) -> :
lines = [
,
,
,
,
,
,
,
,
,
,
,
,
,
,
]
total_exposure =
sub_id .subcontractors:
exposure = .calculate_exposure(sub_id)
total_exposure += exposure.exposure
lines.append(
)
lines.extend([
,
,
,
])
missing = .get_missing_waivers()
missing:
lines.append( )
lines.append( )
m missing[: ]:
lines.append(
)
:
lines.append( )
.join(lines)
Quick Start
tracker = LienWaiverTracker("PRJ-001" , "Office Tower" )
tracker.add_subcontractor(
"SUB-001" , "ABC Mechanical" , "HVAC" ,
contract_amount=500000 ,
contact_name="John Smith" ,
contact_email="john@abcmech.com"
)
tracker.add_subcontractor(
"SUB-002" , "XYZ Electric" , "Electrical" ,
contract_amount=350000 ,
contact_name="Jane Doe" ,
contact_email="jane@xyzelectric.com"
)
pa1 = tracker.create_payment_application(
number=1 ,
period_end=datetime.now(),
subcontractor_id="SUB-001" ,
amount_requested=50000
)
waiver_id = f"LW-SUB-001-1"
tracker.receive_waiver(waiver_id, "/waivers/sub001_pa1.pdf" , "PM" )
result = tracker.can_release_payment("SUB-001" , 1 )
print (f"Can release: {result['can_release' ]} - {result['reason' ]} " )
exposure = tracker.calculate_exposure("SUB-001" )
print (f"Lien exposure: ${exposure.exposure:,.2 f} " )
print (tracker.generate_report())
Requirements
pip install (no external dependencies)
class
LienWaiver
id
str
str
int
float
Optional
None
str
""
str
""
str
""
@dataclass
class
PaymentApplication
int
str
float
float
float
bool
False
Optional
None
@dataclass
class
LienExposure
str
str
float
float
float
float
class
LienWaiverTracker
"""Track and manage construction lien waivers."""
def
__init__
self, project_id: str , project_name: str
self
self
self
Dict
str
self
Dict
str
self
Dict
str
def
add_subcontractor
self, id : str , name: str , trade: str ,
contract_amount: float , contact_name: str ,
contact_email: str , tier: int = 1
"""Add subcontractor to tracking."""
id
id
self
id
return
def
create_payment_application
self, number: int , period_end: datetime,
subcontractor_id: str , amount_requested: float ,
retainage_rate: float = 0.10
"""Create payment application record."""
if
not
in
self
raise
f"Subcontractor {subcontractor_id} not found"
f"{subcontractor_id} -{number} "
self
self
return
def
request_waiver
self, subcontractor_id: str , pay_app_number: int ,
through_date: datetime, amount: float ,
waiver_type: WaiverType = WaiverType.CONDITIONAL_PROGRESS
"""Request lien waiver from subcontractor."""
f"LW-{subcontractor_id} -{pay_app_number} "
id
self
return
def
receive_waiver
self, waiver_id: str , file_path: str ,
verified_by: str = ""
"""Record receipt of lien waiver."""
if
not
in
self
raise
f"Waiver {waiver_id} not found"
self
self
return
def
verify_waiver
self, waiver_id: str , verified_by: str
"""Verify waiver details are correct."""
if
not
in
self
raise
f"Waiver {waiver_id} not found"
self
return
def
reject_waiver
self, waiver_id: str , reason: str
"""Reject waiver (incorrect amount, wrong form, etc.)."""
if
not
in
self
raise
f"Waiver {waiver_id} not found"
self
f"Rejected: {reason} "
return
def
convert_to_unconditional
self, waiver_id: str , payment_date: datetime
"""Convert conditional waiver to unconditional after payment clears."""
if
not
in
self
raise
f"Waiver {waiver_id} not found"
self
if
else
return
self
def
_check_pay_app_waivers
self, subcontractor_id: str , pay_app_number: int
"""Check if all waivers for pay app are received."""
f"{subcontractor_id} -{pay_app_number} "
if
not
in
self
return
self
for
in
self
if
and
all
in
for
in
def
calculate_exposure
self, subcontractor_id: str
"""Calculate lien exposure for subcontractor."""
if
not
in
self
raise
f"Subcontractor {subcontractor_id} not found"
self
sum
for
in
self
if
and
sum
for
in
self
if
and
in
and
in
sum
for
in
self
if
and
in
and
in
return
def
get_missing_waivers
self
List
Dict
"""Get list of missing or pending waivers."""
for
in
self
if
in
self
"waiver_id"
id
"subcontractor"
if
else
"pay_app"
"amount"
"type"
"requested_date"
"days_outstanding"
return
sorted
lambda
"days_outstanding"
def
get_waiver_status_by_sub
self, subcontractor_id: str
Dict
"""Get waiver status summary for subcontractor."""
if
not
in
self
raise
f"Subcontractor {subcontractor_id} not found"
self
for
in
self
if
for
in
0
1
return
"subcontractor"
"total_waivers"
len
"by_status"
"total_amount"
sum
for
in
"verified_amount"
sum
for
in
if
def
can_release_payment
self, subcontractor_id: str , pay_app_number: int
Dict
"""Check if payment can be released."""
f"{subcontractor_id} -{pay_app_number} "
if
not
in
self
return
"can_release"
False
"reason"
"Payment application not found"
self
for
in
self
if
and
and
if
not
return
"can_release"
False
"reason"
"No conditional waiver received"
for
in
if
not
in
return
"can_release"
False
"reason"
f"Waiver {w.id } not verified"
return
"can_release"
True
"reason"
"All waivers verified"
"amount"
def
generate_report
self
str
"""Generate lien waiver status report."""
"# Lien Waiver Status Report"
""
f"**Project:** {self.project_name} "
f"**Date:** {datetime.now().strftime('%Y-%m-%d' )} "
""
"## Summary"
""
f"- Total Subcontractors: {len (self.subcontractors)} "
f"- Total Waivers Tracked: {len (self.waivers)} "
f"- Missing Waivers: {len (self.get_missing_waivers())} "
""
"## Exposure by Subcontractor"
""
"| Subcontractor | Paid | Unconditional | Exposure |"
"|---------------|------|---------------|----------|"
0
for
in
self
self
f"| {exposure.subcontractor_name} | ${exposure.total_paid:,.0 f} | "
f"${exposure.unconditional_waivers:,.0 f} | ${exposure.exposure:,.0 f} |"
f"| **TOTAL** | | | **${total_exposure:,.0 f} ** |"
""
"## Missing Waivers"
""
self
if
"| Subcontractor | Pay App | Amount | Days Outstanding |"
"|---------------|---------|--------|------------------|"
for
in
10
f"| {m['subcontractor' ]} | #{m['pay_app' ]} | "
f"${m['amount' ]:,.0 f} | {m['days_outstanding' ]} |"
else
"*No missing waivers*"
return
"\n"