| 1 | """Deterministic business applicability; no company names or provider outcomes.""" |
| 2 | from dataclasses import dataclass, field |
| 3 | import re |
| 4 | from typing import Mapping |
| 5 | |
| 6 | |
| 7 | @dataclass(frozen=True) |
| 8 | class RequirementApplicability: |
| 9 | state: str = "APPLICABLE" |
| 10 | reason: str | None = None |
| 11 | classification: str | None = None |
| 12 | source: str | None = None |
| 13 | excluded_inputs: Mapping[str, str] = field(default_factory=dict) |
| 14 | |
| 15 | |
| 16 | def classify_requirements(sector: str | None, industry: str | None, source: str | None): |
| 17 | """Unknown/broad classifications never justify excluding a requirement. |
| 18 | |
| 19 | The order/capacity area concerns production and contracted delivery. General |
| 20 | financial-company guidance remains available to growth/news/governance. |
| 21 | Software backlog remains applicable even without industrial plant capacity. |
| 22 | """ |
| 23 | text = re.sub(r"[^a-z0-9]+", " ", industry.casefold()).strip() if industry else "" |
| 24 | classification = f"{sector or 'unknown'} / {industry or 'unknown'}" |
| 25 | common = dict(classification=classification, source=source) |
| 26 | result = {} |
| 27 | if not text: |
| 28 | result["ORDER_BOOK_CAPEX_GUIDANCE"] = RequirementApplicability( |
| 29 | "UNKNOWN", "BUSINESS_CLASSIFICATION_UNAVAILABLE", **common) |
| 30 | return result |
| 31 | financial = any(term in text for term in ( |
| 32 | "stock exchanges", "financial exchanges", "financial data", "banks", |
| 33 | "banking", "insurance", "asset management", "capital markets", |
| 34 | "investment banking", "financial market infrastructure", |
| 35 | )) |
| 36 | if financial: |
| 37 | result["ORDER_BOOK_CAPEX_GUIDANCE"] = RequirementApplicability( |
| 38 | "NOT_APPLICABLE", "DOMAIN_NOT_APPLICABLE:NON_PRODUCTION_FINANCIAL_BUSINESS", **common) |
| 39 | result["BUSINESS_QUALITY_FACTS"] = RequirementApplicability( |
| 40 | "PARTIALLY_APPLICABLE", "INDUSTRIAL_ROCE_NOT_APPLICABLE", **common, |
| 41 | excluded_inputs={"ROCE": "INDUSTRIAL_CAPITAL_EMPLOYED_NOT_APPLICABLE"}) |
| 42 | elif "software" in text: |
| 43 | result["ORDER_BOOK_CAPEX_GUIDANCE"] = RequirementApplicability( |
| 44 | "PARTIALLY_APPLICABLE", "SOFTWARE_BACKLOG_APPLIES_WITHOUT_INDUSTRIAL_CAPACITY", **common, |
| 45 | excluded_inputs={"CAPACITY_OR_CAPEX_OR_COMMISSIONING": "INDUSTRIAL_PRODUCTION_CAPACITY_NOT_APPLICABLE"}) |
| 46 | else: |
| 47 | # Manufacturing, EPC, defence and utilities retain all applicable targets. |
| 48 | result["ORDER_BOOK_CAPEX_GUIDANCE"] = RequirementApplicability( |
| 49 | "APPLICABLE", "PRODUCTION_OR_CONTRACTED_DELIVERY_REQUIREMENTS_RETAINED", **common) |
| 50 | return result |