// Documentation / Wiki — keyword index, articles, release notes const DOC_CATEGORIES = [ { id: "getting-started", label: "Getting Started", icon: "book" }, { id: "modules", label: "Modules", icon: "grid" }, { id: "roles", label: "Roles & Access", icon: "shield" }, { id: "workflows", label: "Workflows", icon: "arrowRight" }, { id: "integrations", label: "Integrations", icon: "bolt" }, { id: "faq", label: "FAQ", icon: "chat" }, { id: "releases", label: "Release Notes", icon: "history" }, ]; const DOC_ARTICLES = [ // -------- Getting Started -------- { id: "gs-overview", category: "getting-started", title: "Welcome to TCMS", tags: ["overview", "tcms", "ocean finance", "apa"], updated: "2025-05-12", author: "Ocean Finance", excerpt: "What TCMS is, who it's for, and how the modules fit together.", blocks: [ { type: "p", text: "TCMS (Terminal Contract Management System) is the global single source of truth for terminal contracts, cost rates, rebate terms, and volume performance across APA Ocean Operations." }, { type: "callout", tone: "info", title: "What's inside", text: "Rate Repository · Rate Health · Rate Calculator · AI Assistant · Rebate Monitor · Volume Tracker · TCO Analysis · Export · Access · Admin." }, { type: "h2", text: "Who uses TCMS" }, { type: "ul", items: [ "Rate Focals maintain rate data and renew expiring rates.", "FBPs analyse cost trends, run simulations and produce monthly TCO reports.", "Procurement uploads contracts (DIFY parses them) and logs rebate settlements.", "Operations / Finance staff use the Calculator for cost estimation only.", "Admins configure metadata, ROE, approval routing, and review audit logs.", ]}, { type: "h2", text: "Key concepts" }, { type: "kv", rows: [ ["Rate", "A per-unit cost charged by a terminal (e.g. CY Handling, Storage)."], ["Rebate", "A post-invoice incentive paid to Maersk if volume or performance thresholds are met."], ["MVC", "Minimum Volume Commitment — contractual TEU floor."], ["TCO", "Total Cost of Ownership — net cost per TEU after rebates."], ["ROE", "Rate of Exchange — local currency to USD."], ]}, ], related: ["gs-quickstart", "mod-rates", "role-matrix"], }, { id: "gs-quickstart", category: "getting-started", title: "Quickstart by role", tags: ["quickstart", "tutorial", "roles", "first time"], updated: "2025-05-10", excerpt: "Step-by-step first-day instructions for each TCMS role.", blocks: [ { type: "p", text: "First time signing in? Find your role below and follow the steps." }, { type: "h3", text: "Rate Focal (edit)" }, { type: "ol", items: [ "Confirm your region/area scope in the top bar.", "Open Rate Repository → review expiring rates flagged in red.", "Use Rate Health → Expiry Alerts to plan renewals.", "Add new rates via Add Rate, or bulk via Import.", "Save — the Quality Validation engine runs automatically.", ]}, { type: "h3", text: "FBP" }, { type: "ol", items: [ "Open the TCO Analysis dashboard to see your region's cost league.", "Drill into a high-cost terminal to see month-by-month breakdown.", "Use the What-if simulator to model rate changes before negotiation.", "Schedule the Monthly TCO Report from the TCO menu.", ]}, { type: "h3", text: "Procurement" }, { type: "ol", items: [ "Upload a contract PDF via Rate Repository → Import → Contract PDF (AI).", "Review the DIFY-extracted preview, fix anything below 0.8 confidence.", "Configure rebate terms in Rebate Monitor.", "Log settlements quarterly from Rebate Monitor → Settlements.", ]}, ], related: ["mod-rates", "mod-rebate", "wf-import"], }, // -------- Modules -------- { id: "mod-rates", category: "modules", title: "Rate Repository", tags: ["rates", "repository", "cost types", "tiers", "currency"], updated: "2025-05-08", excerpt: "Browse, create, import and audit all terminal rates.", blocks: [ { type: "p", text: "The Rate Repository is the canonical list of all terminal rates. Every entry carries terminal, cost type, charge unit, equipment size, cargo type, local rate, currency, effective and expiry dates, contract reference, and full audit metadata." }, { type: "h2", text: "Working with the rate list" }, { type: "ul", items: [ "Use the filter chips at the top to narrow by region, terminal, cost type, status.", "Sort any column by clicking the header.", "Click a row to open the detail drawer with full change history.", "Local rate and ≈ USD are shown side-by-side using the active ROE.", ]}, { type: "h2", text: "Adding rates" }, { type: "p", text: "Three paths are supported:" }, { type: "table", headers: ["Method", "Use when", "Role"], rows: [ ["Manual form", "Single rate, you know the values", "edit, admin"], ["Excel template", "Bulk entry from spreadsheet (≤ 500 rows)", "edit, admin"], ["DIFY contract PDF", "Brand new contract PDF — let AI extract", "edit, procurement, admin"], ]}, { type: "callout", tone: "warn", title: "Overlap detection", text: "If you add a rate for a Terminal × Cost Type × Unit combination that already has an active overlapping rate, TCMS will warn before saving and offer to supersede the older record." }, ], related: ["mod-health", "wf-import", "mod-calc"], }, { id: "mod-health", category: "modules", title: "Rate Health Dashboard", tags: ["health", "completeness", "expiry", "validation", "quality"], updated: "2025-05-13", excerpt: "Real-time data quality view — completeness, expiry alerts, validation rules.", blocks: [ { type: "p", text: "Three panels keep your rate dataset reliable:" }, { type: "h3", text: "Completeness" }, { type: "p", text: "Shows expected Cost Type × Equipment × Cargo combinations per terminal and flags missing rates in red. Each terminal has a completeness ring (0–100%)." }, { type: "h3", text: "Expiry Alerts" }, { type: "p", text: "Lists rates expiring within a configurable window (30 / 60 / 90 days). Traffic-light coding: red ≤ 14 days, amber 15–30, yellow 31–60. Notification emails are sent automatically at 60 / 30 / 7 days before expiry via Power Automate." }, { type: "h3", text: "Quality Validation" }, { type: "p", text: "Eight rules (QV-01 through QV-08) run on every save and on-demand. Errors block save; warnings allow save with notice." }, { type: "kv", rows: [ ["QV-01", "Duplicate Rate (Error)"], ["QV-02", "Date Range Overlap (Error) — auto-fix available"], ["QV-03", "Date Gap (Warning)"], ["QV-04", "Inverted Dates (Error)"], ["QV-05", "Zero / Negative Rate (Warning)"], ["QV-06", "Missing Mandatory Tier (Warning)"], ["QV-07", "ROE Missing for Currency (Error)"], ["QV-08", "Orphan Terminal (Warning)"], ]}, ], related: ["mod-rates", "role-matrix"], }, { id: "mod-calc", category: "modules", title: "Rate Calculator", tags: ["calculator", "cost estimation", "tiered", "storage", "USD"], updated: "2025-05-09", excerpt: "Cost estimation tool — available to every role, output in USD.", blocks: [ { type: "p", text: "The Calculator returns USD cost based on terminal, cost type, unit, quantity and effective date. The system pulls the active local rate, converts to USD via the active ROE, and shows the breakdown." }, { type: "callout", tone: "info", title: "Tiered cost types", text: "For Storage, the form switches to a multi-tier breakdown — enter quantities per tier (Day 1–3, Day 4+) and TCMS produces a per-tier subtotal." }, { type: "callout", tone: "tip", title: "rate_calculator role", text: "Users with the rate_calculator role see ONLY the final USD total — underlying rates and contracts are masked. This is the minimum-access surface for Ops/Finance staff who need numbers but not commercial data." }, ], related: ["mod-rates", "role-calculator"], }, { id: "mod-ai", category: "modules", title: "AI Assistant (DIFY)", tags: ["ai", "dify", "qa", "comparison", "simulation"], updated: "2025-05-11", excerpt: "Natural-language Q&A over rate data — comparison, trend, simulation, lookup.", blocks: [ { type: "p", text: "The Assistant is powered by DIFY workflows with access to the rate database via a secure server-to-server API. Queries are always scoped to the user's region/area on the backend before reaching the LLM." }, { type: "h2", text: "Supported queries" }, { type: "ul", items: [ "Comparison — 'Compare CY Handling across all North Asia terminals for Q2 2025.'", "Trend — 'Show how Storage at Ningbo has changed over 2 years.'", "Simulation — 'If CY Handling at Shanghai +10%, what's the impact on 5,000 TEU/month?'", "Lookup — 'What contract covers Tianjin Storage rates?'", ]}, { type: "callout", tone: "warn", title: "Access", text: "Only fbp, procurement and admin roles can use the Assistant. Conversation history is persisted per session." }, ], related: ["mod-rates", "int-dify"], }, { id: "mod-rebate", category: "modules", title: "Rebate Monitor", tags: ["rebate", "tiers", "accrual", "settlement", "revenue leakage"], updated: "2025-05-13", excerpt: "Full rebate lifecycle — contract terms, tier configuration, monthly accrual, settlement.", blocks: [ { type: "p", text: "Rebate Monitor manages contract clauses negotiated by Procurement: from term ingestion through monthly accrual to settlement tracking. It is the financial engine that prevents revenue leakage." }, { type: "h2", text: "Tier types" }, { type: "kv", rows: [ ["Incremental", "Higher rate applies only to volume above the tier threshold."], ["Retroactive", "Once threshold is crossed, higher rate applies to ALL qualifying volume (a 'tier upgrade adjustment' is recorded for the prior period)."], ]}, { type: "h2", text: "Accrual formula" }, { type: "code", text: "Accrual = Volume × Rebate Rate × Applicable Unit Rate × ROE" }, { type: "p", text: "Re-accrual fires automatically after every Volume Tracker import. Discrepancies > 5% between claimed and calculated settlement amounts are flagged for review." }, ], related: ["mod-volume", "mod-tco"], }, { id: "mod-volume", category: "modules", title: "Volume Tracker", tags: ["volume", "teu", "mvc", "commitment", "throughput"], updated: "2025-05-12", excerpt: "Monthly throughput data — feeds rebate accrual, TCO and MVC monitoring.", blocks: [ { type: "p", text: "Volume Tracker captures actual TEU and moves by terminal × period × equipment × cargo × move type. Monthly CSV/Excel uploads validated server-side; restatements supported with full audit log." }, { type: "h2", text: "MVC monitoring" }, { type: "p", text: "Terminals with a Minimum Volume Commitment clause appear in the Commitment Tracker tab. When annualised YTD pace drops below 95% of contract MVC, the system emails FBP + Procurement via Power Automate." }, { type: "callout", tone: "info", title: "Downstream effects", text: "Every volume commit triggers automatic re-accrual of linked rebate contracts and refreshes the TCO league table." }, ], related: ["mod-rebate", "mod-tco", "wf-volume-upload"], }, { id: "mod-tco", category: "modules", title: "TCO Analysis", tags: ["tco", "total cost", "benchmark", "waterfall", "what-if", "negotiation"], updated: "2025-05-13", excerpt: "Synthesises rates + volume + rebates into a per-terminal cost benchmark.", blocks: [ { type: "p", text: "TCO answers: 'what does this terminal actually cost us, per TEU, net of rebates?' It is the primary analytical surface for FBPs and the evidence base Procurement brings into renegotiations." }, { type: "h2", text: "Five views" }, { type: "ul", items: [ "Cost League — sortable terminal ranking with traffic-light vs regional average.", "Waterfall — cost build-up CY → Storage → Reefer → Other → Gross → Rebate → Net.", "Benchmarking — direct cross-terminal comparison, including by cost-type slice.", "Cost Trend — rolling 12-month line chart with CCFI/SCFI overlay; YoY variance decomposition.", "What-if — slide rate or volume assumptions and see Net/TEU and annual P&L impact instantly.", ]}, { type: "callout", tone: "tip", title: "Rate change impact alerts", text: "When a rate is updated, the TCO engine computes the full-year P&L impact at current volume pace and notifies the relevant FBP." }, ], related: ["mod-rebate", "mod-volume"], }, // -------- Roles -------- { id: "role-matrix", category: "roles", title: "Permission matrix", tags: ["roles", "rbac", "permissions", "access"], updated: "2025-05-12", excerpt: "The full role × feature permission table.", blocks: [ { type: "p", text: "Six roles drive what each user can see and do. Roles are scoped by Region/Area — a user can hold different roles in different regions." }, { type: "permMatrix" }, { type: "callout", tone: "warn", title: "Backend enforcement", text: "All API endpoints enforce role + regional scope checks server-side. The frontend hides UI for unavailable features but is NOT a security boundary." }, ], related: ["role-calculator", "wf-access"], }, { id: "role-calculator", category: "roles", title: "About the rate_calculator role", tags: ["rate_calculator", "minimal access", "ops", "finance"], updated: "2025-05-04", excerpt: "The minimum-access surface — calculator only, no rate data.", blocks: [ { type: "p", text: "rate_calculator is designed for Operations and Finance staff who need cost numbers for estimates but should NOT see commercial rate values or contract references." }, { type: "h2", text: "What they see" }, { type: "ul", items: ["The Calculator screen.", "Calculator results in USD only — local rate values are masked.", "Access Request form to request a higher role."]}, { type: "h2", text: "What they don't see" }, { type: "ul", items: ["Rate Repository, Health, Rebate, Volume, TCO, AI, Export, Admin.", "Underlying rate values, currencies, contract refs."]}, ], related: ["role-matrix", "mod-calc"], }, // -------- Workflows -------- { id: "wf-import", category: "workflows", title: "Importing rates from a contract PDF", tags: ["dify", "import", "contract", "pdf", "ai parsing"], updated: "2025-05-08", excerpt: "Step-by-step DIFY contract parsing workflow.", blocks: [ { type: "ol", items: [ "Open Rate Repository → Import → Contract PDF (AI Extraction).", "Drag the contract PDF into the dropzone (max 25 MB).", "DIFY parses asynchronously — you'll get an in-app notification when ready.", "Review the staging table. Each row has a confidence score (0–1). Rows under 0.8 are highlighted.", "Deselect rows that don't apply; correct fields inline.", "Click Confirm Import. System validates and writes to the rate table plus the audit log.", ]}, { type: "callout", tone: "info", title: "PDF retention", text: "TCMS does NOT store the contract PDF. The Contract Reference field is the durable link to the source document — managed outside the system." }, ], related: ["mod-rates", "int-dify"], }, { id: "wf-volume-upload", category: "workflows", title: "Monthly volume upload", tags: ["volume", "upload", "csv", "excel", "rebate trigger"], updated: "2025-05-12", excerpt: "How to upload monthly TEU and what triggers downstream.", blocks: [ { type: "ol", items: [ "Volume Tracker → Upload monthly volume.", "Download the template (includes dropdown validation).", "Fill in terminal × period × equipment × cargo × move type rows.", "Upload the .xlsx — validation runs row by row.", "Review errors (future periods rejected; duplicates flagged).", "Confirm — rebate accruals and TCO refresh in real-time.", ]}, ], related: ["mod-volume", "mod-rebate"], }, { id: "wf-access", category: "workflows", title: "Requesting access", tags: ["access", "approval", "power automate", "contract manager"], updated: "2025-04-22", excerpt: "How access requests get routed and approved.", blocks: [ { type: "ol", items: [ "Access Requests → New request.", "Pick the role and region(s) you need; provide business justification.", "Submit. Power Automate emails the Contract Manager(s) for that region.", "Manager clicks Approve or Reject in the email.", "On approval, access is provisioned automatically; you receive a confirmation email.", ]}, { type: "callout", tone: "warn", title: "SLA", text: "Requests pending more than 3 business days are flagged in the admin queue and reminders are sent to the manager." }, ], related: ["role-matrix"], }, // -------- Integrations -------- { id: "int-dify", category: "integrations", title: "DIFY integration", tags: ["dify", "ai", "api", "json schema", "confidence"], updated: "2025-05-08", excerpt: "Contract parsing schema and Q&A scoping.", blocks: [ { type: "h2", text: "Contract parsing — JSON schema" }, { type: "code", text: '{"rates":[{"terminal_code":"CNSHA","cost_type_code":"CY_HANDLING",\n "charge_unit_code":"PER_TEU","rate_local":620.00,\n "currency_code":"CNY","effective_date":"2025-01-01",\n "expiry_date":"2025-12-31","tier_description":null,\n "notes":"Extracted from clause 4.2","confidence":0.97}]}' }, { type: "h2", text: "Q&A API" }, { type: "ul", items: [ "Authenticated via server-to-server API key (rotated quarterly).", "User identity + regional scope passed to DIFY before each session.", "All queries proxied through TCMS backend to enforce data scoping.", ]}, ], related: ["mod-ai", "wf-import"], }, { id: "int-powerautomate", category: "integrations", title: "Power Automate workflows", tags: ["power automate", "email", "approval", "alerts"], updated: "2025-05-10", excerpt: "Email-based workflows for access requests, MVC alerts, rebate alerts and expiry notifications.", blocks: [ { type: "table", headers: ["Trigger", "Power Automate action", "Recipients"], rows: [ ["Access request submitted", "Send approval email with Approve / Reject", "Contract Manager(s)"], ["Access approved/rejected", "Notify requester", "Requester"], ["Rate expiring 60 / 30 / 7 days", "Send renewal reminder", "Assigned Rate Focal + FBP"], ["MVC pace < 95%", "Send pace alert", "FBP + Procurement"], ["Rebate tier crossed", "Send tier upgrade alert", "FBP + Procurement"], ["Settlement deadline 14 / 3 days", "Send claim reminder", "Procurement"], ]}, ], related: ["wf-access", "mod-volume", "mod-rebate"], }, // -------- FAQ -------- { id: "faq-edit-rate", category: "faq", title: "Why can't I edit a rate I just created?", tags: ["edit", "permission", "scope", "region"], updated: "2025-04-20", excerpt: "Most common cause: regional scope mismatch.", blocks: [ { type: "p", text: "If you have the edit role but can't modify a specific rate, check the region of the rate's terminal. Edit permissions are scoped to your assigned region(s)/area(s). A user can hold edit in one region and read in another." }, { type: "p", text: "If you genuinely need cross-region edit, submit an Access Request for the additional region." }, ], related: ["role-matrix", "wf-access"], }, { id: "faq-calc-zero", category: "faq", title: "Calculator shows $0 — what's wrong?", tags: ["calculator", "zero", "active rate", "roe"], updated: "2025-05-09", excerpt: "Three common causes.", blocks: [ { type: "ul", items: [ "No active rate covers the selected Effective Date — try a different date or check the rate's status.", "ROE missing for the rate's currency on that date — admin must update the ROE table.", "Tiered cost type but no quantity entered per tier — check both tier inputs are > 0.", ]}, ], related: ["mod-calc", "mod-health"], }, { id: "faq-rebate-discrepancy", category: "faq", title: "Why is my settlement flagged for review?", tags: ["rebate", "settlement", "variance", "5%"], updated: "2025-05-11", excerpt: "Variance > 5% between claimed and calculated.", blocks: [ { type: "p", text: "When you log a settlement, TCMS compares the claimed amount against the calculated accrual for the period. If the difference exceeds 5%, the settlement is marked 'In Review' for FBP validation. Common causes:" }, { type: "ul", items: [ "Tier crossed mid-period — calculated accrual may not yet include the retroactive adjustment.", "Volume restatement after settlement was prepared.", "Manual rounding by terminal operator on the credit note.", "ROE changed between accrual date and claim date.", ]}, ], related: ["mod-rebate"], }, // -------- Release Notes -------- { id: "rel-1-1-0", category: "releases", title: "v1.1.0 — Terminal Contract Management System", tags: ["release", "v1.1", "tcms", "rebate", "volume", "tco", "health"], updated: "2025-05-13", author: "Ocean Finance", version: "1.1.0", releaseDate: "2025-05-13", excerpt: "Major release — system rebranded to TCMS, 4 new modules added.", blocks: [ { type: "callout", tone: "tip", title: "What's new in v1.1", text: "System renamed from 'Rate Repository' to TCMS (Terminal Contract Management System). Four new modules expand the scope from rate management to full contract lifecycle." }, { type: "h2", text: "New modules" }, { type: "kv", rows: [ ["Rate Health Dashboard", "Completeness matrix, expiry alerts, 8 validation rules with auto-fix."], ["Rebate Monitor", "Rebate contracts + tier editor + monthly accrual engine + settlement workflow."], ["Volume Tracker", "Monthly TEU upload, MVC commitment monitoring, 6 analytical views."], ["TCO Analysis", "League table, waterfall, benchmarking, trend with CCFI overlay, What-if simulator."], ]}, { type: "h2", text: "Data model changes" }, { type: "ul", items: [ "Rate records gain Equipment Size and Cargo Type fields (backwards compatible — existing rows default to 'All / Any').", "Terminal contract metadata extended with MVC clause + penalty rate fields.", "New entity: Rebate Contract — links to source contract reference.", ]}, { type: "h2", text: "Integrations" }, { type: "ul", items: [ "Power Automate alerts expanded: rate expiry, MVC breach, rebate tier crossing, settlement deadlines.", "DIFY schema unchanged in v1.1 — confidence threshold still 0.8.", ]}, { type: "h2", text: "Permissions" }, { type: "ul", items: [ "FBP: gains read on Rebate Monitor and Volume Tracker, full access to TCO Analysis.", "Procurement: gains Rebate settlement entry, Volume upload, full TCO Analysis.", "Admin: gains MVC configuration and Rebate Contract management.", ]}, { type: "h2", text: "Migration notes" }, { type: "ul", items: [ "All v1.0 rate data is preserved without change.", "Equipment / Cargo for legacy rows are nullable — Rate Health 'Missing' flags help you backfill.", "Bookmarked v1.0 URLs continue to redirect.", ]}, ], related: ["mod-health", "mod-rebate", "mod-volume", "mod-tco"], }, { id: "rel-1-0-2", category: "releases", title: "v1.0.2 — Calculator default fix", tags: ["release", "v1.0.2", "bugfix", "calculator"], updated: "2025-04-28", version: "1.0.2", releaseDate: "2025-04-28", excerpt: "Bug fix release.", blocks: [ { type: "h2", text: "Fixed" }, { type: "ul", items: [ "Calculator default state now lands on an Active rate (previously could show $0 if seed data fell on Draft status).", "Storage tiers (Day 1–3 / Day 4+) explicitly emitted in seed for every terminal.", "DIFY confidence bar colour scale aligned with QV rule thresholds.", ]}, { type: "h2", text: "Improved" }, { type: "ul", items: [ "Filter chip menus close on click outside.", "Toast notifications now auto-dismiss after 3 seconds.", ]}, ], related: ["mod-calc"], }, { id: "rel-1-0-0", category: "releases", title: "v1.0.0 — Initial Rate Repository launch", tags: ["release", "v1.0", "launch", "mvp"], updated: "2025-04-15", version: "1.0.0", releaseDate: "2025-04-15", excerpt: "MVP launch — APA region, core rate CRUD + DIFY + RBAC.", blocks: [ { type: "h2", text: "MVP scope" }, { type: "ul", items: [ "Core rate CRUD with online form, template import, DIFY contract parsing.", "Six roles with region/area scoping.", "Rate Calculator with tiered cost type support.", "AI Assistant (DIFY) for fbp / procurement / admin.", "Export with filter to Excel/CSV.", "Access request workflow via Power Automate.", "Admin console: user management, metadata, ROE, audit log, routing.", ]}, { type: "callout", tone: "info", title: "Rollout", text: "Phased by region: North Asia (Apr 15) → SE Asia (Apr 22) → South Asia Sub-Continent (Apr 29) → Oceania (May 6)." }, ], related: ["gs-overview"], }, ]; // Flat keyword index for search const DOC_INDEX = DOC_ARTICLES.map(a => ({ ...a, searchText: [ a.title, a.excerpt, ...(a.tags || []), ...(a.blocks || []).flatMap(b => { if (b.type === "p" || b.type === "h2" || b.type === "h3" || b.type === "code") return [b.text]; if (b.type === "ul" || b.type === "ol") return b.items || []; if (b.type === "kv") return (b.rows || []).flat(); if (b.type === "table") return [(b.headers || []).join(" "), ...(b.rows || []).flat()]; if (b.type === "callout") return [b.title, b.text]; return []; }), ].join(" \n ").toLowerCase(), })); Object.assign(window, { DOC_CATEGORIES, DOC_ARTICLES, DOC_INDEX });