cwicr-material-procurement
The CWICR Material Procurement skill generates accurate procurement lists from construction material data by calculating gross quantities with industry-standard waste factors, organizing materials by supplier categories, and creating structured purchase orders with delivery scheduling. Use this skill when planning material purchases for construction projects to ensure proper quantities accounting for waste, align orders with project schedules, and optimize supplier grouping for cost-effective bulk ordering.
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction /tmp/cwicr-material-procurement && cp -r /tmp/cwicr-material-procurement/1_DDC_Toolkit/CWICR-Database/cwicr-material-procurement ~/.claude/skills/cwicr-material-procurementSKILL.md
# CWICR Material Procurement
## Business Case
### Problem Statement
Material procurement needs accurate quantity lists:
- What materials are needed?
- How much of each with waste allowance?
- When are they needed on site?
- How to group for suppliers?
### Solution
Generate procurement lists from CWICR material data with waste factors, delivery scheduling, and supplier grouping.
### Business Value
- **Accurate quantities** - Based on validated norms
- **Waste included** - Industry-standard waste factors
- **Timely delivery** - Aligned with schedule
- **Cost optimization** - Bulk ordering opportunities
## Technical Implementation
```python
import pandas as pd
import numpy as np
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from enum import Enum
from collections import defaultdict
class MaterialCategory(Enum):
"""Material categories for procurement."""
CONCRETE = "concrete"
STEEL = "steel"
TIMBER = "timber"
MASONRY = "masonry"
FINISHES = "finishes"
MEP = "mep"
INSULATION = "insulation"
ROOFING = "roofing"
EARTHWORK = "earthwork"
OTHER = "other"
class ProcurementPriority(Enum):
"""Procurement priority levels."""
CRITICAL = 1
HIGH = 2
MEDIUM = 3
LOW = 4
@dataclass
class MaterialItem:
"""Single material item for procurement."""
material_code: str
description: str
category: MaterialCategory
unit: str
net_quantity: float
waste_factor: float
gross_quantity: float
unit_price: float
total_cost: float
lead_time_days: int
required_date: datetime
order_date: datetime
supplier: str = ""
work_item_codes: List[str] = field(default_factory=list)
@dataclass
class ProcurementList:
"""Complete procurement list."""
project_name: str
generated_date: datetime
total_items: int
total_cost: float
items: List[MaterialItem]
by_category: Dict[str, float]
by_supplier: Dict[str, List[MaterialItem]]
# Standard waste factors by material type
WASTE_FACTORS = {
'concrete': 0.05, # 5%
'reinforcement': 0.03, # 3%
'formwork': 0.10, # 10%
'masonry': 0.05, # 5%
'timber': 0.08, # 8%
'drywall': 0.10, # 10%
'tiles': 0.10, # 10%
'paint': 0.05, # 5%
'insulation': 0.05, # 5%
'pipes': 0.03, # 3%
'cables': 0.05, # 5%
'default': 0.05 # 5%
}
# Standard lead times by category (days)
LEAD_TIMES = {
'concrete': 1, # Ready-mix
'reinforcement': 7, # Steel delivery
'formwork': 3, # Standard forms
'masonry': 5, # Block delivery
'timber': 5, # Lumber
'structural_steel': 21, # Fabrication
'windows': 28, # Manufacturing
'doors': 14, # Standard doors
'mep': 14, # MEP equipment
'finishes': 7, # Standard finishes
'default': 7
}
class CWICRMaterialProcurement:
"""Generate procurement lists from CWICR data."""
def __init__(self, cwicr_data: pd.DataFrame,
resources_data: pd.DataFrame = None):
self.work_items = cwicr_data
self.resources = resources_data
self._index_data()
def _index_data(self):
"""Index data for fast lookup."""
if 'work_item_code' in self.work_items.columns:
self._work_index = self.work_items.set_index('work_item_code')
else:
self._work_index = None
def get_waste_factor(self, material_type: str) -> float:
"""Get waste factor for material type."""
material_lower = str(material_type).lower()
for key, factor in WASTE_FACTORS.items():
if key in material_lower:
return factor
return WASTE_FACTORS['default']
def get_lead_time(self, material_type: str) -> int:
"""Get lead time for material type."""
material_lower = str(material_type).lower()
for key, days in LEAD_TIMES.items():
if key in material_lower:
return days
return LEAD_TIMES['default']
def get_category(self, material_type: str) -> MaterialCategory:
"""Determine material category."""
material_lower = str(material_type).lower()
category_mapping = {
'concrete': MaterialCategory.CONCRETE,
'cement': MaterialCategory.CONCRETE,
'steel': MaterialCategory.STEEL,
'rebar': MaterialCategory.STEEL,
'reinforcement': MaterialCategory.STEEL,
'timber': MaterialCategory.TIMBER,
'wood': MaterialCategory.TIMBER,
'lumber': MaterialCategory.TIMBER,
'masonry': MaterialCategory.MASONRY,
'block': MaterialCategory.MASONRY,
'brick': MaterialCategory.MASONRY,
'paint': MaterialCategory.FINISHES,
'tile': MaterialCategory.FINISHES,
'floor': MaterialCategory.FINISHES,
'electrical': MaterialCategory.MEP,
'plumbing': MaterialCategory.MEP,
'hvac': MaterialCategory.MEP,
'insulation': MaterialCategory.INSULATION,
'roof': MaterialCategory.ROOFING
}
for key, cat in category_mapping.items():
if key in material_lower:
return cat
return MaterialCategory.OTHER
def extract_materials(self,
items: List[Dict[str, Any]],
schedule: Dict[str, datetime] = None) -> List[MaterialItem]:
"""Extract material requirements from work items."""
materials = defaultdict(lambda: {
'net_quantity': 0,
'work_items': [],
'required_date': None
})
for item in items:
code = item.get('work_item_code', item.get('code'))
qty = item.get('quantity', 0)
required_date = item.get('Analyze 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.