[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FK0DHS2JJSZWNBD7Q0VREX":3,"skill-same:01M6FK0DHS2JJSZWNBD7Q0VREX":61},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":28,"linkOnly":29,"markdownContent":30,"markdownBody":31,"frontMatter":32,"refName":34,"commitSha":35,"skillDirectory":36,"forksCount":37,"repositoryHtmlUrl":38,"repositoryHomepageUrl":6,"ownerHtmlUrl":39,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":40,"install":41,"resources":54},"01M6FK0DHS2JJSZWNBD7Q0VREX","material-tracker",null,"Track material orders, deliveries, and inventory on construction sites. Monitor lead times, delivery status, and stock levels.","kbarbel640-del\u002Fskills","kbarbel640-del","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F255315490?v=4","01M6CJPPQGCCESXMG3K7BBGQ5J","01M6CJPPX2PB2BCZERFVM2C2B3",1,"MIT","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fmaterial-tracker\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27],"tracker","material","material tracker","status","monitor","inventory","delivery","orders","stock","sites","2026-11-10 10:12:30",false,"---\r\nslug: \"material-tracker\"\r\ndisplay_name: \"Material Tracker\"\r\ndescription: \"Track material orders, deliveries, and inventory on construction sites. Monitor lead times, delivery status, and stock levels.\"\r\n---\r\n\r\n# Material Tracker\r\n\r\n## Business Case\r\n\r\n### Problem Statement\r\nMaterial management challenges:\r\n- Tracking multiple orders\r\n- Coordinating deliveries\r\n- Avoiding stockouts\r\n- Managing lead times\r\n\r\n### Solution\r\nComprehensive material tracking system to monitor orders, deliveries, inventory, and alert on potential issues.\r\n\r\n## Technical Implementation\r\n\r\n```python\r\nimport pandas as pd\r\nfrom typing import Dict, Any, List, Optional\r\nfrom dataclasses import dataclass, field\r\nfrom datetime import date, timedelta\r\nfrom enum import Enum\r\n\r\n\r\nclass OrderStatus(Enum):\r\n    DRAFT = \"draft\"\r\n    SUBMITTED = \"submitted\"\r\n    CONFIRMED = \"confirmed\"\r\n    IN_PRODUCTION = \"in_production\"\r\n    SHIPPED = \"shipped\"\r\n    DELIVERED = \"delivered\"\r\n    PARTIAL = \"partial\"\r\n    CANCELLED = \"cancelled\"\r\n\r\n\r\nclass PriorityLevel(Enum):\r\n    CRITICAL = \"critical\"\r\n    HIGH = \"high\"\r\n    NORMAL = \"normal\"\r\n    LOW = \"low\"\r\n\r\n\r\n@dataclass\r\nclass MaterialOrder:\r\n    order_id: str\r\n    material_code: str\r\n    material_name: str\r\n    supplier: str\r\n    quantity: float\r\n    unit: str\r\n    unit_cost: float\r\n    total_cost: float\r\n    order_date: date\r\n    required_date: date\r\n    expected_delivery: date\r\n    actual_delivery: Optional[date]\r\n    status: OrderStatus\r\n    priority: PriorityLevel\r\n    delivered_qty: float = 0\r\n    notes: str = \"\"\r\n\r\n\r\n@dataclass\r\nclass InventoryItem:\r\n    material_code: str\r\n    material_name: str\r\n    current_stock: float\r\n    unit: str\r\n    min_stock: float\r\n    max_stock: float\r\n    reorder_point: float\r\n    location: str\r\n    last_updated: date\r\n\r\n\r\n@dataclass\r\nclass Delivery:\r\n    delivery_id: str\r\n    order_id: str\r\n    delivery_date: date\r\n    quantity: float\r\n    received_by: str\r\n    condition: str  # good, damaged, partial\r\n    notes: str = \"\"\r\n\r\n\r\nclass MaterialTracker:\r\n    \"\"\"Track construction materials.\"\"\"\r\n\r\n    def __init__(self, project_name: str):\r\n        self.project_name = project_name\r\n        self.orders: Dict[str, MaterialOrder] = {}\r\n        self.inventory: Dict[str, InventoryItem] = {}\r\n        self.deliveries: List[Delivery] = []\r\n\r\n    def create_order(self,\r\n                     order_id: str,\r\n                     material_code: str,\r\n                     material_name: str,\r\n                     supplier: str,\r\n                     quantity: float,\r\n                     unit: str,\r\n                     unit_cost: float,\r\n                     required_date: date,\r\n                     lead_time_days: int = 14,\r\n                     priority: PriorityLevel = PriorityLevel.NORMAL) -> MaterialOrder:\r\n        \"\"\"Create new material order.\"\"\"\r\n\r\n        order = MaterialOrder(\r\n            order_id=order_id,\r\n            material_code=material_code,\r\n            material_name=material_name,\r\n            supplier=supplier,\r\n            quantity=quantity,\r\n            unit=unit,\r\n            unit_cost=unit_cost,\r\n            total_cost=round(quantity * unit_cost, 2),\r\n            order_date=date.today(),\r\n            required_date=required_date,\r\n            expected_delivery=date.today() + timedelta(days=lead_time_days),\r\n            actual_delivery=None,\r\n            status=OrderStatus.DRAFT,\r\n            priority=priority\r\n        )\r\n\r\n        self.orders[order_id] = order\r\n        return order\r\n\r\n    def update_order_status(self, order_id: str, status: OrderStatus):\r\n        \"\"\"Update order status.\"\"\"\r\n        if order_id in self.orders:\r\n            self.orders[order_id].status = status\r\n\r\n    def record_delivery(self,\r\n                        order_id: str,\r\n                        quantity: float,\r\n                        received_by: str,\r\n                        condition: str = \"good\",\r\n                        notes: str = \"\") -> Optional[Delivery]:\r\n        \"\"\"Record material delivery.\"\"\"\r\n\r\n        if order_id not in self.orders:\r\n            return None\r\n\r\n        order = self.orders[order_id]\r\n\r\n        delivery = Delivery(\r\n            delivery_id=f\"DEL-{len(self.deliveries)+1:04d}\",\r\n            order_id=order_id,\r\n            delivery_date=date.today(),\r\n            quantity=quantity,\r\n            received_by=received_by,\r\n            condition=condition,\r\n            notes=notes\r\n        )\r\n\r\n        self.deliveries.append(delivery)\r\n\r\n        # Update order\r\n        order.delivered_qty += quantity\r\n        order.actual_delivery = date.today()\r\n\r\n        if order.delivered_qty >= order.quantity:\r\n            order.status = OrderStatus.DELIVERED\r\n        else:\r\n            order.status = OrderStatus.PARTIAL\r\n\r\n        # Update inventory\r\n        if order.material_code in self.inventory:\r\n            self.inventory[order.material_code].current_stock += quantity\r\n            self.inventory[order.material_code].last_updated = date.today()\r\n\r\n        return delivery\r\n\r\n    def add_inventory_item(self,\r\n                           material_code: str,\r\n                           material_name: str,\r\n                           current_stock: float,\r\n                           unit: str,\r\n                           min_stock: float,\r\n                           max_stock: float,\r\n                           location: str):\r\n        \"\"\"Add item to inventory tracking.\"\"\"\r\n\r\n        reorder_point = min_stock + (max_stock - min_stock) * 0.3\r\n\r\n        self.inventory[material_code] = InventoryItem(\r\n            material_code=material_code,\r\n            material_name=material_name,\r\n            current_stock=current_stock,\r\n            unit=unit,\r\n            min_stock=min_stock,\r\n            max_stock=max_stock,\r\n            reorder_point=reorder_point,\r\n            location=location,\r\n            last_updated=date.today()\r\n        )\r\n\r\n    def consume_material(self,\r\n                         material_code: str,\r\n                         quantity: float,\r\n                         activity: str = \"\") -> bool:\r\n        \"\"\"Record material consumption.\"\"\"\r\n\r\n        if material_code not in self.inventory:\r\n            return False\r\n\r\n        item = self.inventory[material_code]\r\n        if item.current_stock \u003C quantity:\r\n            return False\r\n\r\n        item.current_stock -= quantity\r\n        item.last_updated = date.today()\r\n        return True\r\n\r\n    def get_pending_orders(self) -> List[MaterialOrder]:\r\n        \"\"\"Get all pending orders.\"\"\"\r\n        return [\r\n            o for o in self.orders.values()\r\n            if o.status not in [OrderStatus.DELIVERED, OrderStatus.CANCELLED]\r\n        ]\r\n\r\n    def get_late_orders(self) -> List[Dict[str, Any]]:\r\n        \"\"\"Get orders that are late or at risk.\"\"\"\r\n\r\n        late = []\r\n        today = date.today()\r\n\r\n        for order in self.orders.values():\r\n            if order.status in [OrderStatus.DELIVERED, OrderStatus.CANCELLED]:\r\n                continue\r\n\r\n            days_late = (today - order.expected_delivery).days\r\n\r\n            if days_late > 0 or (order.required_date - today).days \u003C 3:\r\n                late.append({\r\n                    'order_id': order.order_id,\r\n                    'material': order.material_name,\r\n                    'supplier': order.supplier,\r\n                    'required_date': order.required_date,\r\n                    'expected_delivery': order.expected_delivery,\r\n                    'days_late': max(0, days_late),\r\n                    'days_until_required': (order.required_date - today).days,\r\n                    'status': order.status.value,\r\n                    'priority': order.priority.value\r\n                })\r\n\r\n        return sorted(late, key=lambda x: x['days_until_required'])\r\n\r\n    def get_low_stock_items(self) -> List[Dict[str, Any]]:\r\n        \"\"\"Get items at or below reorder point.\"\"\"\r\n\r\n        low_stock = []\r\n\r\n        for item in self.inventory.values():\r\n            if item.current_stock \u003C= item.reorder_point:\r\n                low_stock.append({\r\n                    'material_code': item.material_code,\r\n                    'material_name': item.material_name,\r\n                    'current_stock': item.current_stock,\r\n                    'reorder_point': item.reorder_point,\r\n                    'min_stock': item.min_stock,\r\n                    'unit': item.unit,\r\n                    'location': item.location,\r\n                    'urgency': 'CRITICAL' if item.current_stock \u003C= item.min_stock else 'REORDER'\r\n                })\r\n\r\n        return sorted(low_stock, key=lambda x: x['current_stock'])\r\n\r\n    def get_delivery_schedule(self, days_ahead: int = 14) -> pd.DataFrame:\r\n        \"\"\"Get expected deliveries for coming days.\"\"\"\r\n\r\n        today = date.today()\r\n        end_date = today + timedelta(days=days_ahead)\r\n\r\n        scheduled = []\r\n\r\n        for order in self.orders.values():\r\n            if order.status in [OrderStatus.DELIVERED, OrderStatus.CANCELLED]:\r\n                continue\r\n\r\n            if today \u003C= order.expected_delivery \u003C= end_date:\r\n                scheduled.append({\r\n                    'Date': order.expected_delivery,\r\n                    'Order ID': order.order_id,\r\n                    'Material': order.material_name,\r\n                    'Quantity': order.quantity,\r\n                    'Unit': order.unit,\r\n                    'Supplier': order.supplier,\r\n                    'Priority': order.priority.value\r\n                })\r\n\r\n        return pd.DataFrame(scheduled).sort_values('Date') if scheduled else pd.DataFrame()\r\n\r\n    def calculate_material_cost_summary(self) -> Dict[str, Any]:\r\n        \"\"\"Calculate material cost summary.\"\"\"\r\n\r\n        total_ordered = sum(o.total_cost for o in self.orders.values())\r\n        total_delivered = sum(\r\n            o.delivered_qty * o.unit_cost\r\n            for o in self.orders.values()\r\n        )\r\n        total_pending = total_ordered - total_delivered\r\n\r\n        by_supplier = {}\r\n        for order in self.orders.values():\r\n            if order.supplier not in by_supplier:\r\n                by_supplier[order.supplier] = 0\r\n            by_supplier[order.supplier] += order.total_cost\r\n\r\n        return {\r\n            'total_ordered': round(total_ordered, 2),\r\n            'total_delivered': round(total_delivered, 2),\r\n            'total_pending': round(total_pending, 2),\r\n            'order_count': len(self.orders),\r\n            'by_supplier': by_supplier\r\n        }\r\n\r\n    def export_to_excel(self, output_path: str) -> str:\r\n        \"\"\"Export material tracking to Excel.\"\"\"\r\n\r\n        with pd.ExcelWriter(output_path, engine='openpyxl') as writer:\r\n            # Orders\r\n            orders_df = pd.DataFrame([\r\n                {\r\n                    'Order ID': o.order_id,\r\n                    'Material': o.material_name,\r\n                    'Supplier': o.supplier,\r\n                    'Quantity': o.quantity,\r\n                    'Unit': o.unit,\r\n                    'Unit Cost': o.unit_cost,\r\n                    'Total Cost': o.total_cost,\r\n                    'Order Date': o.order_date,\r\n                    'Required': o.required_date,\r\n                    'Expected': o.expected_delivery,\r\n                    'Status': o.status.value,\r\n                    'Delivered': o.delivered_qty\r\n                }\r\n                for o in self.orders.values()\r\n            ])\r\n            orders_df.to_excel(writer, sheet_name='Orders', index=False)\r\n\r\n            # Inventory\r\n            if self.inventory:\r\n                inv_df = pd.DataFrame([\r\n                    {\r\n                        'Code': i.material_code,\r\n                        'Name': i.material_name,\r\n                        'Stock': i.current_stock,\r\n                        'Unit': i.unit,\r\n                        'Min': i.min_stock,\r\n                        'Max': i.max_stock,\r\n                        'Reorder Point': i.reorder_point,\r\n                        'Location': i.location\r\n                    }\r\n                    for i in self.inventory.values()\r\n                ])\r\n                inv_df.to_excel(writer, sheet_name='Inventory', index=False)\r\n\r\n            # Late orders\r\n            late = self.get_late_orders()\r\n            if late:\r\n                late_df = pd.DataFrame(late)\r\n                late_df.to_excel(writer, sheet_name='Late Orders', index=False)\r\n\r\n            # Low stock\r\n            low = self.get_low_stock_items()\r\n            if low:\r\n                low_df = pd.DataFrame(low)\r\n                low_df.to_excel(writer, sheet_name='Low Stock', index=False)\r\n\r\n        return output_path\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom datetime import date, timedelta\r\n\r\n# Initialize tracker\r\ntracker = MaterialTracker(\"Office Building A\")\r\n\r\n# Create order\r\norder = tracker.create_order(\r\n    order_id=\"PO-001\",\r\n    material_code=\"CONC-C30\",\r\n    material_name=\"Concrete C30\",\r\n    supplier=\"ABC Ready Mix\",\r\n    quantity=200,\r\n    unit=\"m3\",\r\n    unit_cost=150,\r\n    required_date=date.today() + timedelta(days=10),\r\n    lead_time_days=3,\r\n    priority=PriorityLevel.HIGH\r\n)\r\n\r\n# Update status\r\ntracker.update_order_status(\"PO-001\", OrderStatus.CONFIRMED)\r\n\r\n# Record delivery\r\ntracker.record_delivery(\"PO-001\", quantity=200, received_by=\"John Smith\")\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### 1. Check Late Orders\r\n```python\r\nlate = tracker.get_late_orders()\r\nfor order in late:\r\n    print(f\"{order['order_id']}: {order['days_late']} days late\")\r\n```\r\n\r\n### 2. Low Stock Alert\r\n```python\r\nlow_stock = tracker.get_low_stock_items()\r\nfor item in low_stock:\r\n    print(f\"{item['material_name']}: {item['current_stock']} {item['unit']} - {item['urgency']}\")\r\n```\r\n\r\n### 3. Delivery Schedule\r\n```python\r\nschedule = tracker.get_delivery_schedule(days_ahead=7)\r\nprint(schedule)\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 3.2 - Material Management\r\n","# Material Tracker\r\n\r\n## Business Case\r\n\r\n### Problem Statement\r\nMaterial management challenges:\r\n- Tracking multiple orders\r\n- Coordinating deliveries\r\n- Avoiding stockouts\r\n- Managing lead times\r\n\r\n### Solution\r\nComprehensive material tracking system to monitor orders, deliveries, inventory, and alert on potential issues.\r\n\r\n## Technical Implementation\r\n\r\n```python\r\nimport pandas as pd\r\nfrom typing import Dict, Any, List, Optional\r\nfrom dataclasses import dataclass, field\r\nfrom datetime import date, timedelta\r\nfrom enum import Enum\r\n\r\n\r\nclass OrderStatus(Enum):\r\n    DRAFT = \"draft\"\r\n    SUBMITTED = \"submitted\"\r\n    CONFIRMED = \"confirmed\"\r\n    IN_PRODUCTION = \"in_production\"\r\n    SHIPPED = \"shipped\"\r\n    DELIVERED = \"delivered\"\r\n    PARTIAL = \"partial\"\r\n    CANCELLED = \"cancelled\"\r\n\r\n\r\nclass PriorityLevel(Enum):\r\n    CRITICAL = \"critical\"\r\n    HIGH = \"high\"\r\n    NORMAL = \"normal\"\r\n    LOW = \"low\"\r\n\r\n\r\n@dataclass\r\nclass MaterialOrder:\r\n    order_id: str\r\n    material_code: str\r\n    material_name: str\r\n    supplier: str\r\n    quantity: float\r\n    unit: str\r\n    unit_cost: float\r\n    total_cost: float\r\n    order_date: date\r\n    required_date: date\r\n    expected_delivery: date\r\n    actual_delivery: Optional[date]\r\n    status: OrderStatus\r\n    priority: PriorityLevel\r\n    delivered_qty: float = 0\r\n    notes: str = \"\"\r\n\r\n\r\n@dataclass\r\nclass InventoryItem:\r\n    material_code: str\r\n    material_name: str\r\n    current_stock: float\r\n    unit: str\r\n    min_stock: float\r\n    max_stock: float\r\n    reorder_point: float\r\n    location: str\r\n    last_updated: date\r\n\r\n\r\n@dataclass\r\nclass Delivery:\r\n    delivery_id: str\r\n    order_id: str\r\n    delivery_date: date\r\n    quantity: float\r\n    received_by: str\r\n    condition: str  # good, damaged, partial\r\n    notes: str = \"\"\r\n\r\n\r\nclass MaterialTracker:\r\n    \"\"\"Track construction materials.\"\"\"\r\n\r\n    def __init__(self, project_name: str):\r\n        self.project_name = project_name\r\n        self.orders: Dict[str, MaterialOrder] = {}\r\n        self.inventory: Dict[str, InventoryItem] = {}\r\n        self.deliveries: List[Delivery] = []\r\n\r\n    def create_order(self,\r\n                     order_id: str,\r\n                     material_code: str,\r\n                     material_name: str,\r\n                     supplier: str,\r\n                     quantity: float,\r\n                     unit: str,\r\n                     unit_cost: float,\r\n                     required_date: date,\r\n                     lead_time_days: int = 14,\r\n                     priority: PriorityLevel = PriorityLevel.NORMAL) -> MaterialOrder:\r\n        \"\"\"Create new material order.\"\"\"\r\n\r\n        order = MaterialOrder(\r\n            order_id=order_id,\r\n            material_code=material_code,\r\n            material_name=material_name,\r\n            supplier=supplier,\r\n            quantity=quantity,\r\n            unit=unit,\r\n            unit_cost=unit_cost,\r\n            total_cost=round(quantity * unit_cost, 2),\r\n            order_date=date.today(),\r\n            required_date=required_date,\r\n            expected_delivery=date.today() + timedelta(days=lead_time_days),\r\n            actual_delivery=None,\r\n            status=OrderStatus.DRAFT,\r\n            priority=priority\r\n        )\r\n\r\n        self.orders[order_id] = order\r\n        return order\r\n\r\n    def update_order_status(self, order_id: str, status: OrderStatus):\r\n        \"\"\"Update order status.\"\"\"\r\n        if order_id in self.orders:\r\n            self.orders[order_id].status = status\r\n\r\n    def record_delivery(self,\r\n                        order_id: str,\r\n                        quantity: float,\r\n                        received_by: str,\r\n                        condition: str = \"good\",\r\n                        notes: str = \"\") -> Optional[Delivery]:\r\n        \"\"\"Record material delivery.\"\"\"\r\n\r\n        if order_id not in self.orders:\r\n            return None\r\n\r\n        order = self.orders[order_id]\r\n\r\n        delivery = Delivery(\r\n            delivery_id=f\"DEL-{len(self.deliveries)+1:04d}\",\r\n            order_id=order_id,\r\n            delivery_date=date.today(),\r\n            quantity=quantity,\r\n            received_by=received_by,\r\n            condition=condition,\r\n            notes=notes\r\n        )\r\n\r\n        self.deliveries.append(delivery)\r\n\r\n        # Update order\r\n        order.delivered_qty += quantity\r\n        order.actual_delivery = date.today()\r\n\r\n        if order.delivered_qty >= order.quantity:\r\n            order.status = OrderStatus.DELIVERED\r\n        else:\r\n            order.status = OrderStatus.PARTIAL\r\n\r\n        # Update inventory\r\n        if order.material_code in self.inventory:\r\n            self.inventory[order.material_code].current_stock += quantity\r\n            self.inventory[order.material_code].last_updated = date.today()\r\n\r\n        return delivery\r\n\r\n    def add_inventory_item(self,\r\n                           material_code: str,\r\n                           material_name: str,\r\n                           current_stock: float,\r\n                           unit: str,\r\n                           min_stock: float,\r\n                           max_stock: float,\r\n                           location: str):\r\n        \"\"\"Add item to inventory tracking.\"\"\"\r\n\r\n        reorder_point = min_stock + (max_stock - min_stock) * 0.3\r\n\r\n        self.inventory[material_code] = InventoryItem(\r\n            material_code=material_code,\r\n            material_name=material_name,\r\n            current_stock=current_stock,\r\n            unit=unit,\r\n            min_stock=min_stock,\r\n            max_stock=max_stock,\r\n            reorder_point=reorder_point,\r\n            location=location,\r\n            last_updated=date.today()\r\n        )\r\n\r\n    def consume_material(self,\r\n                         material_code: str,\r\n                         quantity: float,\r\n                         activity: str = \"\") -> bool:\r\n        \"\"\"Record material consumption.\"\"\"\r\n\r\n        if material_code not in self.inventory:\r\n            return False\r\n\r\n        item = self.inventory[material_code]\r\n        if item.current_stock \u003C quantity:\r\n            return False\r\n\r\n        item.current_stock -= quantity\r\n        item.last_updated = date.today()\r\n        return True\r\n\r\n    def get_pending_orders(self) -> List[MaterialOrder]:\r\n        \"\"\"Get all pending orders.\"\"\"\r\n        return [\r\n            o for o in self.orders.values()\r\n            if o.status not in [OrderStatus.DELIVERED, OrderStatus.CANCELLED]\r\n        ]\r\n\r\n    def get_late_orders(self) -> List[Dict[str, Any]]:\r\n        \"\"\"Get orders that are late or at risk.\"\"\"\r\n\r\n        late = []\r\n        today = date.today()\r\n\r\n        for order in self.orders.values():\r\n            if order.status in [OrderStatus.DELIVERED, OrderStatus.CANCELLED]:\r\n                continue\r\n\r\n            days_late = (today - order.expected_delivery).days\r\n\r\n            if days_late > 0 or (order.required_date - today).days \u003C 3:\r\n                late.append({\r\n                    'order_id': order.order_id,\r\n                    'material': order.material_name,\r\n                    'supplier': order.supplier,\r\n                    'required_date': order.required_date,\r\n                    'expected_delivery': order.expected_delivery,\r\n                    'days_late': max(0, days_late),\r\n                    'days_until_required': (order.required_date - today).days,\r\n                    'status': order.status.value,\r\n                    'priority': order.priority.value\r\n                })\r\n\r\n        return sorted(late, key=lambda x: x['days_until_required'])\r\n\r\n    def get_low_stock_items(self) -> List[Dict[str, Any]]:\r\n        \"\"\"Get items at or below reorder point.\"\"\"\r\n\r\n        low_stock = []\r\n\r\n        for item in self.inventory.values():\r\n            if item.current_stock \u003C= item.reorder_point:\r\n                low_stock.append({\r\n                    'material_code': item.material_code,\r\n                    'material_name': item.material_name,\r\n                    'current_stock': item.current_stock,\r\n                    'reorder_point': item.reorder_point,\r\n                    'min_stock': item.min_stock,\r\n                    'unit': item.unit,\r\n                    'location': item.location,\r\n                    'urgency': 'CRITICAL' if item.current_stock \u003C= item.min_stock else 'REORDER'\r\n                })\r\n\r\n        return sorted(low_stock, key=lambda x: x['current_stock'])\r\n\r\n    def get_delivery_schedule(self, days_ahead: int = 14) -> pd.DataFrame:\r\n        \"\"\"Get expected deliveries for coming days.\"\"\"\r\n\r\n        today = date.today()\r\n        end_date = today + timedelta(days=days_ahead)\r\n\r\n        scheduled = []\r\n\r\n        for order in self.orders.values():\r\n            if order.status in [OrderStatus.DELIVERED, OrderStatus.CANCELLED]:\r\n                continue\r\n\r\n            if today \u003C= order.expected_delivery \u003C= end_date:\r\n                scheduled.append({\r\n                    'Date': order.expected_delivery,\r\n                    'Order ID': order.order_id,\r\n                    'Material': order.material_name,\r\n                    'Quantity': order.quantity,\r\n                    'Unit': order.unit,\r\n                    'Supplier': order.supplier,\r\n                    'Priority': order.priority.value\r\n                })\r\n\r\n        return pd.DataFrame(scheduled).sort_values('Date') if scheduled else pd.DataFrame()\r\n\r\n    def calculate_material_cost_summary(self) -> Dict[str, Any]:\r\n        \"\"\"Calculate material cost summary.\"\"\"\r\n\r\n        total_ordered = sum(o.total_cost for o in self.orders.values())\r\n        total_delivered = sum(\r\n            o.delivered_qty * o.unit_cost\r\n            for o in self.orders.values()\r\n        )\r\n        total_pending = total_ordered - total_delivered\r\n\r\n        by_supplier = {}\r\n        for order in self.orders.values():\r\n            if order.supplier not in by_supplier:\r\n                by_supplier[order.supplier] = 0\r\n            by_supplier[order.supplier] += order.total_cost\r\n\r\n        return {\r\n            'total_ordered': round(total_ordered, 2),\r\n            'total_delivered': round(total_delivered, 2),\r\n            'total_pending': round(total_pending, 2),\r\n            'order_count': len(self.orders),\r\n            'by_supplier': by_supplier\r\n        }\r\n\r\n    def export_to_excel(self, output_path: str) -> str:\r\n        \"\"\"Export material tracking to Excel.\"\"\"\r\n\r\n        with pd.ExcelWriter(output_path, engine='openpyxl') as writer:\r\n            # Orders\r\n            orders_df = pd.DataFrame([\r\n                {\r\n                    'Order ID': o.order_id,\r\n                    'Material': o.material_name,\r\n                    'Supplier': o.supplier,\r\n                    'Quantity': o.quantity,\r\n                    'Unit': o.unit,\r\n                    'Unit Cost': o.unit_cost,\r\n                    'Total Cost': o.total_cost,\r\n                    'Order Date': o.order_date,\r\n                    'Required': o.required_date,\r\n                    'Expected': o.expected_delivery,\r\n                    'Status': o.status.value,\r\n                    'Delivered': o.delivered_qty\r\n                }\r\n                for o in self.orders.values()\r\n            ])\r\n            orders_df.to_excel(writer, sheet_name='Orders', index=False)\r\n\r\n            # Inventory\r\n            if self.inventory:\r\n                inv_df = pd.DataFrame([\r\n                    {\r\n                        'Code': i.material_code,\r\n                        'Name': i.material_name,\r\n                        'Stock': i.current_stock,\r\n                        'Unit': i.unit,\r\n                        'Min': i.min_stock,\r\n                        'Max': i.max_stock,\r\n                        'Reorder Point': i.reorder_point,\r\n                        'Location': i.location\r\n                    }\r\n                    for i in self.inventory.values()\r\n                ])\r\n                inv_df.to_excel(writer, sheet_name='Inventory', index=False)\r\n\r\n            # Late orders\r\n            late = self.get_late_orders()\r\n            if late:\r\n                late_df = pd.DataFrame(late)\r\n                late_df.to_excel(writer, sheet_name='Late Orders', index=False)\r\n\r\n            # Low stock\r\n            low = self.get_low_stock_items()\r\n            if low:\r\n                low_df = pd.DataFrame(low)\r\n                low_df.to_excel(writer, sheet_name='Low Stock', index=False)\r\n\r\n        return output_path\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom datetime import date, timedelta\r\n\r\n# Initialize tracker\r\ntracker = MaterialTracker(\"Office Building A\")\r\n\r\n# Create order\r\norder = tracker.create_order(\r\n    order_id=\"PO-001\",\r\n    material_code=\"CONC-C30\",\r\n    material_name=\"Concrete C30\",\r\n    supplier=\"ABC Ready Mix\",\r\n    quantity=200,\r\n    unit=\"m3\",\r\n    unit_cost=150,\r\n    required_date=date.today() + timedelta(days=10),\r\n    lead_time_days=3,\r\n    priority=PriorityLevel.HIGH\r\n)\r\n\r\n# Update status\r\ntracker.update_order_status(\"PO-001\", OrderStatus.CONFIRMED)\r\n\r\n# Record delivery\r\ntracker.record_delivery(\"PO-001\", quantity=200, received_by=\"John Smith\")\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### 1. Check Late Orders\r\n```python\r\nlate = tracker.get_late_orders()\r\nfor order in late:\r\n    print(f\"{order['order_id']}: {order['days_late']} days late\")\r\n```\r\n\r\n### 2. Low Stock Alert\r\n```python\r\nlow_stock = tracker.get_low_stock_items()\r\nfor item in low_stock:\r\n    print(f\"{item['material_name']}: {item['current_stock']} {item['unit']} - {item['urgency']}\")\r\n```\r\n\r\n### 3. Delivery Schedule\r\n```python\r\nschedule = tracker.get_delivery_schedule(days_ahead=7)\r\nprint(schedule)\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 3.2 - Material Management\r\n",{"slug":5,"description":7,"display_name":33},"Material Tracker","main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fdatadrivenconstruction\u002Fmaterial-tracker",0,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del","2026-08-23 22:39:37",{"source":8,"skillName":5,"commands":42,"prompt":52,"zipAvailable":53},[43,46,49],{"tool":44,"command":45},"npx","npx skills add kbarbel640-del\u002Fskills --skill material-tracker",{"tool":47,"command":48},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill material-tracker",{"tool":50,"command":51},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill material-tracker","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fmaterial-tracker\u002FSKILL.md",true,[55],{"path":56,"resourceType":57,"resourceTypeDesc":58,"sizeBytes":59,"sourceHtmlUrl":60},"_meta.json","REFERENCE","参考文档",300,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fmaterial-tracker\u002F_meta.json",[62,93,122,143,149,168],{"skillNo":63,"name":64,"nameZh":6,"description":65,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":66,"categories":67,"keywords":73,"publishedAt":28},"01M6G8J55967D6281ACMKAKTEQ","crowd-prompting","A marketplace where AI agents improve prompts, system instructions, tool descriptions, and other text-based content with domain expertise from real-world operations — and earn tokens for valuable contributions.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzzadrian\u002Fcrowd-prompting\u002FSKILL.md",[68],{"categoryNo":69,"categoryName":70,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92],"crowd prompting","prompting","api","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":94,"name":95,"nameZh":6,"description":96,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":104,"publishedAt":28},"01M6G8J0PKPAYVET6BWE8W4C26","dilemm-ai","Compete in DilemmAI, the prisoner's dilemma AI arena at dilemm.ai. Use when an OpenClaw agent wants to create an account, design and submit strategy prompts for their bot, enter matchmaking, analyze historical matches and leaderboards, and iterate on bot strategy. Requires headless browser automation (no API available yet).","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzyori\u002Fdilemm-ai\u002FSKILL.md",[99],{"categoryNo":100,"categoryName":101,"taxonomyType":102,"taxonomyTypeDesc":103},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[105,76,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,81,121],"dilemm ai","arena","analyze","browser","openclaw agent","create","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":123,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":126,"categories":127,"keywords":131,"publishedAt":28},"01M6G8HWAF3K9SW7NP3Z83CPJ6","arxiv-paper-reviews","Interact with arXiv Crawler API to fetch papers, read reviews, and submit comments. Use when working with arXiv papers, fetching paper lists by date\u002Fcategory\u002Finterest, viewing paper details with comments, or submitting paper reviews via API at http:\u002F\u002F150.158.152.82:8000.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Fweak-accept\u002FSKILL.md",[128],{"categoryNo":129,"categoryName":130,"taxonomyType":102,"taxonomyTypeDesc":103},"01JBSEEDCAT000000000000021","资料检索与研究",[132,133,134,135,136,137,138,77,139,119,121,140,76,141,142],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","fetch","read","http","via",{"skillNo":144,"name":124,"nameZh":6,"description":125,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":145,"categories":146,"keywords":148,"publishedAt":28},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[147],{"categoryNo":129,"categoryName":130,"taxonomyType":102,"taxonomyTypeDesc":103},[135,134,133,132,142,137,138,77,136,119,121,139,140,76,141],{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":153,"categories":154,"keywords":155,"publishedAt":28},"01M6G8HM95Y64JNVFC2HN4E2BG","git-summary","Get a quick summary of the current Git repository including status, recent commits, branches, and contributors.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzweack\u002Fgit-summary\u002FSKILL.md",[],[156,157,158,159,160,161,21,162,163,164,165,166,167],"git","summary","git summary","commits","repository","win32","linux","contributors","true","quick","get","branches",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":178,"publishedAt":28},"01M6G8HGEGF05CNEJCGVYFSC4R","agent-constitution","Interact with AgentConstitution governance contracts on Base Sepolia. Check compliance, read rules, log actions, query governance state.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fztsalexey\u002Fagent-constitution\u002FSKILL.md",[174,175],{"categoryNo":100,"categoryName":101,"taxonomyType":102,"taxonomyTypeDesc":103},{"categoryNo":176,"categoryName":177,"taxonomyType":71,"taxonomyTypeDesc":72},"01JBSEEDCAT000000000000037","律师与法务",[179,180,181,182,77,183,184,34,185,140,186,187,188,189,190,90,191,192,193],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]