{
  "schemaVersion": "1.0",
  "item": {
    "slug": "unit-price-database-manager",
    "name": "Unit Price Database Manager",
    "source": "tencent",
    "type": "skill",
    "category": "数据分析",
    "sourceUrl": "https://clawhub.ai/datadrivenconstruction/unit-price-database-manager",
    "canonicalUrl": "https://clawhub.ai/datadrivenconstruction/unit-price-database-manager",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/unit-price-database-manager",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=unit-price-database-manager",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "claw.json",
      "instructions.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/unit-price-database-manager"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/unit-price-database-manager",
    "agentPageUrl": "https://openagent3.xyz/skills/unit-price-database-manager/agent",
    "manifestUrl": "https://openagent3.xyz/skills/unit-price-database-manager/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/unit-price-database-manager/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Overview",
        "body": "Manage and maintain construction unit price databases. Update prices from vendors, apply location and time adjustments, track price history, and ensure estimating accuracy."
      },
      {
        "title": "Business Case",
        "body": "Accurate unit prices are critical for:\n\nCompetitive Bids: Win work with accurate pricing\nCost Control: Avoid budget surprises\nVendor Management: Track supplier pricing\nHistorical Analysis: Understand price trends"
      },
      {
        "title": "Technical Implementation",
        "body": "from dataclasses import dataclass, field\nfrom typing import List, Dict, Any, Optional\nfrom datetime import datetime, date\nfrom decimal import Decimal\nimport pandas as pd\nimport json\n\n@dataclass\nclass UnitPrice:\n    code: str\n    description: str\n    unit: str\n    base_price: Decimal\n    labor_cost: Decimal\n    material_cost: Decimal\n    equipment_cost: Decimal\n    effective_date: date\n    expiration_date: Optional[date] = None\n    source: str = \"\"\n    vendor: str = \"\"\n    location: str = \"National Average\"\n    notes: str = \"\"\n    tags: List[str] = field(default_factory=list)\n\n@dataclass\nclass PriceUpdate:\n    code: str\n    old_price: Decimal\n    new_price: Decimal\n    change_pct: float\n    updated_at: datetime\n    updated_by: str\n    reason: str\n\n@dataclass\nclass VendorQuote:\n    vendor_name: str\n    item_code: str\n    quoted_price: Decimal\n    quote_date: date\n    valid_until: date\n    quantity_break: Optional[int] = None\n    notes: str = \"\"\n\nclass UnitPriceDatabaseManager:\n    \"\"\"Manage construction unit price databases.\"\"\"\n\n    # Location adjustment factors\n    LOCATION_FACTORS = {\n        'New York': 1.32, 'San Francisco': 1.28, 'Los Angeles': 1.15,\n        'Chicago': 1.12, 'Boston': 1.18, 'Seattle': 1.08,\n        'Denver': 1.02, 'National Average': 1.00,\n        'Houston': 0.92, 'Dallas': 0.89, 'Phoenix': 0.93,\n        'Atlanta': 0.91, 'Miami': 0.95\n    }\n\n    def __init__(self, db_path: str = None):\n        self.prices: Dict[str, UnitPrice] = {}\n        self.price_history: Dict[str, List[UnitPrice]] = {}\n        self.vendor_quotes: Dict[str, List[VendorQuote]] = {}\n        self.updates: List[PriceUpdate] = []\n        self.db_path = db_path\n\n    def add_price(self, price: UnitPrice) -> str:\n        \"\"\"Add or update a unit price.\"\"\"\n        code = price.code\n\n        # Track history\n        if code in self.prices:\n            if code not in self.price_history:\n                self.price_history[code] = []\n            self.price_history[code].append(self.prices[code])\n\n            # Record update\n            old_price = self.prices[code].base_price\n            if old_price != price.base_price:\n                change_pct = float((price.base_price - old_price) / old_price * 100)\n                self.updates.append(PriceUpdate(\n                    code=code,\n                    old_price=old_price,\n                    new_price=price.base_price,\n                    change_pct=change_pct,\n                    updated_at=datetime.now(),\n                    updated_by=\"system\",\n                    reason=\"Price update\"\n                ))\n\n        self.prices[code] = price\n        return code\n\n    def get_price(self, code: str, location: str = None,\n                  as_of_date: date = None) -> Optional[UnitPrice]:\n        \"\"\"Get unit price with optional location adjustment.\"\"\"\n        if code not in self.prices:\n            return None\n\n        price = self.prices[code]\n\n        # Check date validity\n        if as_of_date:\n            if price.effective_date > as_of_date:\n                # Look in history\n                if code in self.price_history:\n                    for hist_price in reversed(self.price_history[code]):\n                        if hist_price.effective_date <= as_of_date:\n                            if hist_price.expiration_date is None or hist_price.expiration_date >= as_of_date:\n                                price = hist_price\n                                break\n\n            if price.expiration_date and price.expiration_date < as_of_date:\n                return None\n\n        # Apply location factor\n        if location and location != price.location:\n            adjusted = UnitPrice(\n                code=price.code,\n                description=price.description,\n                unit=price.unit,\n                base_price=self._apply_location_factor(price.base_price, price.location, location),\n                labor_cost=self._apply_location_factor(price.labor_cost, price.location, location),\n                material_cost=price.material_cost,  # Materials less location-sensitive\n                equipment_cost=self._apply_location_factor(price.equipment_cost, price.location, location),\n                effective_date=price.effective_date,\n                expiration_date=price.expiration_date,\n                source=price.source,\n                vendor=price.vendor,\n                location=location,\n                notes=f\"Adjusted from {price.location}\",\n                tags=price.tags\n            )\n            return adjusted\n\n        return price\n\n    def _apply_location_factor(self, amount: Decimal, from_loc: str, to_loc: str) -> Decimal:\n        \"\"\"Apply location adjustment factor.\"\"\"\n        from_factor = self.LOCATION_FACTORS.get(from_loc, 1.0)\n        to_factor = self.LOCATION_FACTORS.get(to_loc, 1.0)\n        return Decimal(str(float(amount) * to_factor / from_factor))\n\n    def apply_escalation(self, percentage: float, categories: List[str] = None,\n                         effective_date: date = None) -> int:\n        \"\"\"Apply escalation to prices.\"\"\"\n        if effective_date is None:\n            effective_date = date.today()\n\n        count = 0\n        factor = Decimal(str(1 + percentage / 100))\n\n        for code, price in self.prices.items():\n            if categories and not any(tag in price.tags for tag in categories):\n                continue\n\n            old_price = price.base_price\n            new_price = UnitPrice(\n                code=price.code,\n                description=price.description,\n                unit=price.unit,\n                base_price=price.base_price * factor,\n                labor_cost=price.labor_cost * factor,\n                material_cost=price.material_cost * factor,\n                equipment_cost=price.equipment_cost * factor,\n                effective_date=effective_date,\n                source=f\"Escalated {percentage}% from {price.source}\",\n                vendor=price.vendor,\n                location=price.location,\n                tags=price.tags\n            )\n\n            self.add_price(new_price)\n            count += 1\n\n        return count\n\n    def add_vendor_quote(self, quote: VendorQuote):\n        \"\"\"Add a vendor quote.\"\"\"\n        code = quote.item_code\n        if code not in self.vendor_quotes:\n            self.vendor_quotes[code] = []\n        self.vendor_quotes[code].append(quote)\n\n    def get_best_price(self, code: str, quantity: int = 1) -> Optional[Dict]:\n        \"\"\"Get best available price from vendors.\"\"\"\n        if code not in self.vendor_quotes:\n            return None\n\n        valid_quotes = []\n        today = date.today()\n\n        for quote in self.vendor_quotes[code]:\n            if quote.valid_until >= today:\n                if quote.quantity_break is None or quantity >= quote.quantity_break:\n                    valid_quotes.append(quote)\n\n        if not valid_quotes:\n            return None\n\n        best = min(valid_quotes, key=lambda q: q.quoted_price)\n\n        return {\n            'vendor': best.vendor_name,\n            'price': best.quoted_price,\n            'valid_until': best.valid_until,\n            'all_quotes': [\n                {'vendor': q.vendor_name, 'price': q.quoted_price}\n                for q in sorted(valid_quotes, key=lambda x: x.quoted_price)\n            ]\n        }\n\n    def search_prices(self, query: str = None, category: str = None,\n                       min_price: float = None, max_price: float = None) -> List[UnitPrice]:\n        \"\"\"Search prices by various criteria.\"\"\"\n        results = []\n\n        for code, price in self.prices.items():\n            # Text search\n            if query:\n                query_lower = query.lower()\n                if (query_lower not in code.lower() and\n                    query_lower not in price.description.lower()):\n                    continue\n\n            # Category filter\n            if category and category not in price.tags:\n                continue\n\n            # Price range\n            if min_price and float(price.base_price) < min_price:\n                continue\n            if max_price and float(price.base_price) > max_price:\n                continue\n\n            results.append(price)\n\n        return results\n\n    def get_price_history(self, code: str) -> List[Dict]:\n        \"\"\"Get price history for an item.\"\"\"\n        history = []\n\n        if code in self.price_history:\n            for price in self.price_history[code]:\n                history.append({\n                    'date': price.effective_date,\n                    'price': float(price.base_price),\n                    'source': price.source\n                })\n\n        if code in self.prices:\n            history.append({\n                'date': self.prices[code].effective_date,\n                'price': float(self.prices[code].base_price),\n                'source': self.prices[code].source\n            })\n\n        return sorted(history, key=lambda x: x['date'])\n\n    def analyze_price_trends(self, code: str) -> Dict:\n        \"\"\"Analyze price trends for an item.\"\"\"\n        history = self.get_price_history(code)\n\n        if len(history) < 2:\n            return {'trend': 'insufficient_data'}\n\n        prices = [h['price'] for h in history]\n        dates = [h['date'] for h in history]\n\n        # Calculate changes\n        first_price = prices[0]\n        last_price = prices[-1]\n        total_change = (last_price - first_price) / first_price * 100\n\n        # Calculate annualized rate\n        days = (dates[-1] - dates[0]).days\n        years = days / 365.25\n        if years > 0:\n            annual_rate = ((last_price / first_price) ** (1 / years) - 1) * 100\n        else:\n            annual_rate = 0\n\n        return {\n            'code': code,\n            'first_price': first_price,\n            'last_price': last_price,\n            'total_change_pct': total_change,\n            'annual_rate_pct': annual_rate,\n            'data_points': len(history),\n            'period_years': years,\n            'trend': 'increasing' if total_change > 5 else 'decreasing' if total_change < -5 else 'stable'\n        }\n\n    def import_from_csv(self, file_path: str) -> int:\n        \"\"\"Import prices from CSV file.\"\"\"\n        df = pd.read_csv(file_path)\n        count = 0\n\n        for _, row in df.iterrows():\n            price = UnitPrice(\n                code=row['code'],\n                description=row['description'],\n                unit=row['unit'],\n                base_price=Decimal(str(row['base_price'])),\n                labor_cost=Decimal(str(row.get('labor_cost', 0))),\n                material_cost=Decimal(str(row.get('material_cost', 0))),\n                equipment_cost=Decimal(str(row.get('equipment_cost', 0))),\n                effective_date=date.today() if 'effective_date' not in row else pd.to_datetime(row['effective_date']).date(),\n                source=row.get('source', 'CSV Import'),\n                tags=row.get('tags', '').split(',') if 'tags' in row else []\n            )\n            self.add_price(price)\n            count += 1\n\n        return count\n\n    def export_to_csv(self, file_path: str, location: str = None) -> int:\n        \"\"\"Export prices to CSV file.\"\"\"\n        data = []\n\n        for code, price in self.prices.items():\n            if location:\n                price = self.get_price(code, location)\n\n            data.append({\n                'code': price.code,\n                'description': price.description,\n                'unit': price.unit,\n                'base_price': float(price.base_price),\n                'labor_cost': float(price.labor_cost),\n                'material_cost': float(price.material_cost),\n                'equipment_cost': float(price.equipment_cost),\n                'location': price.location,\n                'effective_date': price.effective_date.isoformat(),\n                'source': price.source,\n                'tags': ','.join(price.tags)\n            })\n\n        df = pd.DataFrame(data)\n        df.to_csv(file_path, index=False)\n        return len(data)\n\n    def validate_prices(self) -> List[Dict]:\n        \"\"\"Validate prices for issues.\"\"\"\n        issues = []\n\n        for code, price in self.prices.items():\n            # Check for expired prices\n            if price.expiration_date and price.expiration_date < date.today():\n                issues.append({\n                    'code': code,\n                    'issue': 'expired',\n                    'message': f\"Price expired on {price.expiration_date}\"\n                })\n\n            # Check for old prices\n            age_days = (date.today() - price.effective_date).days\n            if age_days > 365:\n                issues.append({\n                    'code': code,\n                    'issue': 'stale',\n                    'message': f\"Price is {age_days} days old\"\n                })\n\n            # Check for zero prices\n            if price.base_price <= 0:\n                issues.append({\n                    'code': code,\n                    'issue': 'invalid',\n                    'message': \"Zero or negative price\"\n                })\n\n            # Check component breakdown\n            total_components = price.labor_cost + price.material_cost + price.equipment_cost\n            if total_components > 0 and abs(float(price.base_price - total_components)) > 0.01:\n                issues.append({\n                    'code': code,\n                    'issue': 'mismatch',\n                    'message': f\"Component costs don't match total: {total_components} vs {price.base_price}\"\n                })\n\n        return issues\n\n    def generate_report(self) -> str:\n        \"\"\"Generate database status report.\"\"\"\n        lines = [\"# Unit Price Database Report\", \"\"]\n        lines.append(f\"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}\")\n        lines.append(f\"**Total Items:** {len(self.prices):,}\")\n        lines.append(\"\")\n\n        # Category breakdown\n        categories = {}\n        for price in self.prices.values():\n            for tag in price.tags:\n                categories[tag] = categories.get(tag, 0) + 1\n\n        if categories:\n            lines.append(\"## Items by Category\")\n            for cat, count in sorted(categories.items(), key=lambda x: -x[1]):\n                lines.append(f\"- {cat}: {count}\")\n            lines.append(\"\")\n\n        # Recent updates\n        recent_updates = sorted(self.updates, key=lambda x: x.updated_at, reverse=True)[:10]\n        if recent_updates:\n            lines.append(\"## Recent Updates\")\n            for update in recent_updates:\n                lines.append(f\"- {update.code}: {update.change_pct:+.1f}% on {update.updated_at.strftime('%Y-%m-%d')}\")\n            lines.append(\"\")\n\n        # Validation issues\n        issues = self.validate_prices()\n        if issues:\n            lines.append(\"## Validation Issues\")\n            lines.append(f\"Total issues: {len(issues)}\")\n            for issue in issues[:10]:\n                lines.append(f\"- {issue['code']}: {issue['message']}\")\n\n        return \"\\n\".join(lines)"
      },
      {
        "title": "Quick Start",
        "body": "from decimal import Decimal\nfrom datetime import date\n\n# Initialize manager\nmanager = UnitPriceDatabaseManager()\n\n# Add unit prices\nmanager.add_price(UnitPrice(\n    code=\"033000.10\",\n    description=\"Cast-in-place concrete, 4000 PSI\",\n    unit=\"CY\",\n    base_price=Decimal(\"450.00\"),\n    labor_cost=Decimal(\"150.00\"),\n    material_cost=Decimal(\"250.00\"),\n    equipment_cost=Decimal(\"50.00\"),\n    effective_date=date(2026, 1, 1),\n    source=\"RSMeans 2026\",\n    tags=[\"concrete\", \"structural\"]\n))\n\n# Get price with location adjustment\nprice = manager.get_price(\"033000.10\", location=\"New York\")\nprint(f\"NYC price: ${price.base_price}/CY\")\n\n# Add vendor quote\nmanager.add_vendor_quote(VendorQuote(\n    vendor_name=\"ABC Concrete\",\n    item_code=\"033000.10\",\n    quoted_price=Decimal(\"420.00\"),\n    quote_date=date.today(),\n    valid_until=date(2026, 3, 31)\n))\n\n# Get best price\nbest = manager.get_best_price(\"033000.10\")\nprint(f\"Best price: ${best['price']} from {best['vendor']}\")\n\n# Apply escalation\ncount = manager.apply_escalation(3.5, categories=[\"concrete\"])\nprint(f\"Escalated {count} items by 3.5%\")\n\n# Generate report\nprint(manager.generate_report())"
      },
      {
        "title": "Dependencies",
        "body": "pip install pandas"
      }
    ],
    "body": "Unit Price Database Manager for Construction\nOverview\n\nManage and maintain construction unit price databases. Update prices from vendors, apply location and time adjustments, track price history, and ensure estimating accuracy.\n\nBusiness Case\n\nAccurate unit prices are critical for:\n\nCompetitive Bids: Win work with accurate pricing\nCost Control: Avoid budget surprises\nVendor Management: Track supplier pricing\nHistorical Analysis: Understand price trends\nTechnical Implementation\nfrom dataclasses import dataclass, field\nfrom typing import List, Dict, Any, Optional\nfrom datetime import datetime, date\nfrom decimal import Decimal\nimport pandas as pd\nimport json\n\n@dataclass\nclass UnitPrice:\n    code: str\n    description: str\n    unit: str\n    base_price: Decimal\n    labor_cost: Decimal\n    material_cost: Decimal\n    equipment_cost: Decimal\n    effective_date: date\n    expiration_date: Optional[date] = None\n    source: str = \"\"\n    vendor: str = \"\"\n    location: str = \"National Average\"\n    notes: str = \"\"\n    tags: List[str] = field(default_factory=list)\n\n@dataclass\nclass PriceUpdate:\n    code: str\n    old_price: Decimal\n    new_price: Decimal\n    change_pct: float\n    updated_at: datetime\n    updated_by: str\n    reason: str\n\n@dataclass\nclass VendorQuote:\n    vendor_name: str\n    item_code: str\n    quoted_price: Decimal\n    quote_date: date\n    valid_until: date\n    quantity_break: Optional[int] = None\n    notes: str = \"\"\n\nclass UnitPriceDatabaseManager:\n    \"\"\"Manage construction unit price databases.\"\"\"\n\n    # Location adjustment factors\n    LOCATION_FACTORS = {\n        'New York': 1.32, 'San Francisco': 1.28, 'Los Angeles': 1.15,\n        'Chicago': 1.12, 'Boston': 1.18, 'Seattle': 1.08,\n        'Denver': 1.02, 'National Average': 1.00,\n        'Houston': 0.92, 'Dallas': 0.89, 'Phoenix': 0.93,\n        'Atlanta': 0.91, 'Miami': 0.95\n    }\n\n    def __init__(self, db_path: str = None):\n        self.prices: Dict[str, UnitPrice] = {}\n        self.price_history: Dict[str, List[UnitPrice]] = {}\n        self.vendor_quotes: Dict[str, List[VendorQuote]] = {}\n        self.updates: List[PriceUpdate] = []\n        self.db_path = db_path\n\n    def add_price(self, price: UnitPrice) -> str:\n        \"\"\"Add or update a unit price.\"\"\"\n        code = price.code\n\n        # Track history\n        if code in self.prices:\n            if code not in self.price_history:\n                self.price_history[code] = []\n            self.price_history[code].append(self.prices[code])\n\n            # Record update\n            old_price = self.prices[code].base_price\n            if old_price != price.base_price:\n                change_pct = float((price.base_price - old_price) / old_price * 100)\n                self.updates.append(PriceUpdate(\n                    code=code,\n                    old_price=old_price,\n                    new_price=price.base_price,\n                    change_pct=change_pct,\n                    updated_at=datetime.now(),\n                    updated_by=\"system\",\n                    reason=\"Price update\"\n                ))\n\n        self.prices[code] = price\n        return code\n\n    def get_price(self, code: str, location: str = None,\n                  as_of_date: date = None) -> Optional[UnitPrice]:\n        \"\"\"Get unit price with optional location adjustment.\"\"\"\n        if code not in self.prices:\n            return None\n\n        price = self.prices[code]\n\n        # Check date validity\n        if as_of_date:\n            if price.effective_date > as_of_date:\n                # Look in history\n                if code in self.price_history:\n                    for hist_price in reversed(self.price_history[code]):\n                        if hist_price.effective_date <= as_of_date:\n                            if hist_price.expiration_date is None or hist_price.expiration_date >= as_of_date:\n                                price = hist_price\n                                break\n\n            if price.expiration_date and price.expiration_date < as_of_date:\n                return None\n\n        # Apply location factor\n        if location and location != price.location:\n            adjusted = UnitPrice(\n                code=price.code,\n                description=price.description,\n                unit=price.unit,\n                base_price=self._apply_location_factor(price.base_price, price.location, location),\n                labor_cost=self._apply_location_factor(price.labor_cost, price.location, location),\n                material_cost=price.material_cost,  # Materials less location-sensitive\n                equipment_cost=self._apply_location_factor(price.equipment_cost, price.location, location),\n                effective_date=price.effective_date,\n                expiration_date=price.expiration_date,\n                source=price.source,\n                vendor=price.vendor,\n                location=location,\n                notes=f\"Adjusted from {price.location}\",\n                tags=price.tags\n            )\n            return adjusted\n\n        return price\n\n    def _apply_location_factor(self, amount: Decimal, from_loc: str, to_loc: str) -> Decimal:\n        \"\"\"Apply location adjustment factor.\"\"\"\n        from_factor = self.LOCATION_FACTORS.get(from_loc, 1.0)\n        to_factor = self.LOCATION_FACTORS.get(to_loc, 1.0)\n        return Decimal(str(float(amount) * to_factor / from_factor))\n\n    def apply_escalation(self, percentage: float, categories: List[str] = None,\n                         effective_date: date = None) -> int:\n        \"\"\"Apply escalation to prices.\"\"\"\n        if effective_date is None:\n            effective_date = date.today()\n\n        count = 0\n        factor = Decimal(str(1 + percentage / 100))\n\n        for code, price in self.prices.items():\n            if categories and not any(tag in price.tags for tag in categories):\n                continue\n\n            old_price = price.base_price\n            new_price = UnitPrice(\n                code=price.code,\n                description=price.description,\n                unit=price.unit,\n                base_price=price.base_price * factor,\n                labor_cost=price.labor_cost * factor,\n                material_cost=price.material_cost * factor,\n                equipment_cost=price.equipment_cost * factor,\n                effective_date=effective_date,\n                source=f\"Escalated {percentage}% from {price.source}\",\n                vendor=price.vendor,\n                location=price.location,\n                tags=price.tags\n            )\n\n            self.add_price(new_price)\n            count += 1\n\n        return count\n\n    def add_vendor_quote(self, quote: VendorQuote):\n        \"\"\"Add a vendor quote.\"\"\"\n        code = quote.item_code\n        if code not in self.vendor_quotes:\n            self.vendor_quotes[code] = []\n        self.vendor_quotes[code].append(quote)\n\n    def get_best_price(self, code: str, quantity: int = 1) -> Optional[Dict]:\n        \"\"\"Get best available price from vendors.\"\"\"\n        if code not in self.vendor_quotes:\n            return None\n\n        valid_quotes = []\n        today = date.today()\n\n        for quote in self.vendor_quotes[code]:\n            if quote.valid_until >= today:\n                if quote.quantity_break is None or quantity >= quote.quantity_break:\n                    valid_quotes.append(quote)\n\n        if not valid_quotes:\n            return None\n\n        best = min(valid_quotes, key=lambda q: q.quoted_price)\n\n        return {\n            'vendor': best.vendor_name,\n            'price': best.quoted_price,\n            'valid_until': best.valid_until,\n            'all_quotes': [\n                {'vendor': q.vendor_name, 'price': q.quoted_price}\n                for q in sorted(valid_quotes, key=lambda x: x.quoted_price)\n            ]\n        }\n\n    def search_prices(self, query: str = None, category: str = None,\n                       min_price: float = None, max_price: float = None) -> List[UnitPrice]:\n        \"\"\"Search prices by various criteria.\"\"\"\n        results = []\n\n        for code, price in self.prices.items():\n            # Text search\n            if query:\n                query_lower = query.lower()\n                if (query_lower not in code.lower() and\n                    query_lower not in price.description.lower()):\n                    continue\n\n            # Category filter\n            if category and category not in price.tags:\n                continue\n\n            # Price range\n            if min_price and float(price.base_price) < min_price:\n                continue\n            if max_price and float(price.base_price) > max_price:\n                continue\n\n            results.append(price)\n\n        return results\n\n    def get_price_history(self, code: str) -> List[Dict]:\n        \"\"\"Get price history for an item.\"\"\"\n        history = []\n\n        if code in self.price_history:\n            for price in self.price_history[code]:\n                history.append({\n                    'date': price.effective_date,\n                    'price': float(price.base_price),\n                    'source': price.source\n                })\n\n        if code in self.prices:\n            history.append({\n                'date': self.prices[code].effective_date,\n                'price': float(self.prices[code].base_price),\n                'source': self.prices[code].source\n            })\n\n        return sorted(history, key=lambda x: x['date'])\n\n    def analyze_price_trends(self, code: str) -> Dict:\n        \"\"\"Analyze price trends for an item.\"\"\"\n        history = self.get_price_history(code)\n\n        if len(history) < 2:\n            return {'trend': 'insufficient_data'}\n\n        prices = [h['price'] for h in history]\n        dates = [h['date'] for h in history]\n\n        # Calculate changes\n        first_price = prices[0]\n        last_price = prices[-1]\n        total_change = (last_price - first_price) / first_price * 100\n\n        # Calculate annualized rate\n        days = (dates[-1] - dates[0]).days\n        years = days / 365.25\n        if years > 0:\n            annual_rate = ((last_price / first_price) ** (1 / years) - 1) * 100\n        else:\n            annual_rate = 0\n\n        return {\n            'code': code,\n            'first_price': first_price,\n            'last_price': last_price,\n            'total_change_pct': total_change,\n            'annual_rate_pct': annual_rate,\n            'data_points': len(history),\n            'period_years': years,\n            'trend': 'increasing' if total_change > 5 else 'decreasing' if total_change < -5 else 'stable'\n        }\n\n    def import_from_csv(self, file_path: str) -> int:\n        \"\"\"Import prices from CSV file.\"\"\"\n        df = pd.read_csv(file_path)\n        count = 0\n\n        for _, row in df.iterrows():\n            price = UnitPrice(\n                code=row['code'],\n                description=row['description'],\n                unit=row['unit'],\n                base_price=Decimal(str(row['base_price'])),\n                labor_cost=Decimal(str(row.get('labor_cost', 0))),\n                material_cost=Decimal(str(row.get('material_cost', 0))),\n                equipment_cost=Decimal(str(row.get('equipment_cost', 0))),\n                effective_date=date.today() if 'effective_date' not in row else pd.to_datetime(row['effective_date']).date(),\n                source=row.get('source', 'CSV Import'),\n                tags=row.get('tags', '').split(',') if 'tags' in row else []\n            )\n            self.add_price(price)\n            count += 1\n\n        return count\n\n    def export_to_csv(self, file_path: str, location: str = None) -> int:\n        \"\"\"Export prices to CSV file.\"\"\"\n        data = []\n\n        for code, price in self.prices.items():\n            if location:\n                price = self.get_price(code, location)\n\n            data.append({\n                'code': price.code,\n                'description': price.description,\n                'unit': price.unit,\n                'base_price': float(price.base_price),\n                'labor_cost': float(price.labor_cost),\n                'material_cost': float(price.material_cost),\n                'equipment_cost': float(price.equipment_cost),\n                'location': price.location,\n                'effective_date': price.effective_date.isoformat(),\n                'source': price.source,\n                'tags': ','.join(price.tags)\n            })\n\n        df = pd.DataFrame(data)\n        df.to_csv(file_path, index=False)\n        return len(data)\n\n    def validate_prices(self) -> List[Dict]:\n        \"\"\"Validate prices for issues.\"\"\"\n        issues = []\n\n        for code, price in self.prices.items():\n            # Check for expired prices\n            if price.expiration_date and price.expiration_date < date.today():\n                issues.append({\n                    'code': code,\n                    'issue': 'expired',\n                    'message': f\"Price expired on {price.expiration_date}\"\n                })\n\n            # Check for old prices\n            age_days = (date.today() - price.effective_date).days\n            if age_days > 365:\n                issues.append({\n                    'code': code,\n                    'issue': 'stale',\n                    'message': f\"Price is {age_days} days old\"\n                })\n\n            # Check for zero prices\n            if price.base_price <= 0:\n                issues.append({\n                    'code': code,\n                    'issue': 'invalid',\n                    'message': \"Zero or negative price\"\n                })\n\n            # Check component breakdown\n            total_components = price.labor_cost + price.material_cost + price.equipment_cost\n            if total_components > 0 and abs(float(price.base_price - total_components)) > 0.01:\n                issues.append({\n                    'code': code,\n                    'issue': 'mismatch',\n                    'message': f\"Component costs don't match total: {total_components} vs {price.base_price}\"\n                })\n\n        return issues\n\n    def generate_report(self) -> str:\n        \"\"\"Generate database status report.\"\"\"\n        lines = [\"# Unit Price Database Report\", \"\"]\n        lines.append(f\"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}\")\n        lines.append(f\"**Total Items:** {len(self.prices):,}\")\n        lines.append(\"\")\n\n        # Category breakdown\n        categories = {}\n        for price in self.prices.values():\n            for tag in price.tags:\n                categories[tag] = categories.get(tag, 0) + 1\n\n        if categories:\n            lines.append(\"## Items by Category\")\n            for cat, count in sorted(categories.items(), key=lambda x: -x[1]):\n                lines.append(f\"- {cat}: {count}\")\n            lines.append(\"\")\n\n        # Recent updates\n        recent_updates = sorted(self.updates, key=lambda x: x.updated_at, reverse=True)[:10]\n        if recent_updates:\n            lines.append(\"## Recent Updates\")\n            for update in recent_updates:\n                lines.append(f\"- {update.code}: {update.change_pct:+.1f}% on {update.updated_at.strftime('%Y-%m-%d')}\")\n            lines.append(\"\")\n\n        # Validation issues\n        issues = self.validate_prices()\n        if issues:\n            lines.append(\"## Validation Issues\")\n            lines.append(f\"Total issues: {len(issues)}\")\n            for issue in issues[:10]:\n                lines.append(f\"- {issue['code']}: {issue['message']}\")\n\n        return \"\\n\".join(lines)\n\nQuick Start\nfrom decimal import Decimal\nfrom datetime import date\n\n# Initialize manager\nmanager = UnitPriceDatabaseManager()\n\n# Add unit prices\nmanager.add_price(UnitPrice(\n    code=\"033000.10\",\n    description=\"Cast-in-place concrete, 4000 PSI\",\n    unit=\"CY\",\n    base_price=Decimal(\"450.00\"),\n    labor_cost=Decimal(\"150.00\"),\n    material_cost=Decimal(\"250.00\"),\n    equipment_cost=Decimal(\"50.00\"),\n    effective_date=date(2026, 1, 1),\n    source=\"RSMeans 2026\",\n    tags=[\"concrete\", \"structural\"]\n))\n\n# Get price with location adjustment\nprice = manager.get_price(\"033000.10\", location=\"New York\")\nprint(f\"NYC price: ${price.base_price}/CY\")\n\n# Add vendor quote\nmanager.add_vendor_quote(VendorQuote(\n    vendor_name=\"ABC Concrete\",\n    item_code=\"033000.10\",\n    quoted_price=Decimal(\"420.00\"),\n    quote_date=date.today(),\n    valid_until=date(2026, 3, 31)\n))\n\n# Get best price\nbest = manager.get_best_price(\"033000.10\")\nprint(f\"Best price: ${best['price']} from {best['vendor']}\")\n\n# Apply escalation\ncount = manager.apply_escalation(3.5, categories=[\"concrete\"])\nprint(f\"Escalated {count} items by 3.5%\")\n\n# Generate report\nprint(manager.generate_report())\n\nDependencies\npip install pandas"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/datadrivenconstruction/unit-price-database-manager",
    "publisherUrl": "https://clawhub.ai/datadrivenconstruction/unit-price-database-manager",
    "owner": "datadrivenconstruction",
    "version": "2.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/unit-price-database-manager",
    "downloadUrl": "https://openagent3.xyz/downloads/unit-price-database-manager",
    "agentUrl": "https://openagent3.xyz/skills/unit-price-database-manager/agent",
    "manifestUrl": "https://openagent3.xyz/skills/unit-price-database-manager/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/unit-price-database-manager/agent.md"
  }
}