docs: add architecture reference for Claude context
This commit is contained in:
1 parent
160d9077b3
commit
f340fe4886
1 file changed
+130
@@ -0,0 +1,130 @@
|
||||
# Architecture Reference
|
||||
|
||||
_Last updated: 2026-09-23 (v1.5.9)_
|
||||
|
||||
## Data Flow
|
||||
|
||||
```
|
||||
Disco DB (open jobs)
|
||||
│
|
||||
├─► ServiceTrackerService.BuildDashboard()
|
||||
│ │
|
||||
Google Sheet CSV │ ├─► BuildDiscoTile() ─┐
|
||||
│ │ └─► BuildSheetTile() ─┤
|
||||
▼ │ ▼
|
||||
GoogleSheetService List<DashboardTile>
|
||||
(fetch → cache → parse) │
|
||||
▼
|
||||
Bucket sort into:
|
||||
- ReadyForReturn
|
||||
- OnHold
|
||||
- AwaitingVendor
|
||||
- AwaitingParts
|
||||
- Tiles (main grid)
|
||||
│
|
||||
▼
|
||||
DashboardViewModel
|
||||
│
|
||||
▼
|
||||
WebHandler → HTML string
|
||||
```
|
||||
|
||||
## Persistence (JSON files)
|
||||
|
||||
All under `App_Data/Plugins/Disco.Plugins.ServiceTracker/`:
|
||||
|
||||
| File | Contents |
|
||||
|------|---------|
|
||||
| `config.json` | `ServiceTrackerConfig` — priorities, locations, statuses, technicians, sheet config |
|
||||
| `tickets/` | One JSON file per Disco job (`{jobId}.json`) — `ServiceTicket` overrides, notes, changelog |
|
||||
| `external_tickets/` | One JSON file per NTT sheet row (`{internalId}.json`) — same shape as ServiceTicket |
|
||||
| `sheet_cache.csv` | Last fetched CSV from Google; invalidated by `RefreshMinutes` |
|
||||
|
||||
## ID Generation for NTT Tickets
|
||||
|
||||
Stable integer ID from djb2 hash of `timestamp|email|task|issue` (lowercased, trimmed), modulo 800000 + 100000 offset. Collisions resolved by incrementing. IDs are stable across refreshes as long as those four fields don't change.
|
||||
|
||||
## Column Index Contract
|
||||
|
||||
All Google Sheet column indices live in `GoogleSheetConfig`. Current mapping (updated 2026-09-23):
|
||||
|
||||
```
|
||||
0 ColTimestamp — Timestamp
|
||||
1 ColEmail — Email address
|
||||
2 ColTask — What is the task/request?
|
||||
3 ColIssue — Detailed Description
|
||||
4 ColLocation — Location / Classroom
|
||||
5 ColRequestedBy — Requested By
|
||||
6 ColPriority — Priority Level
|
||||
7 ColPreferredDate — Preferred Completion Date
|
||||
8 ColCampus — Campus (location fallback if ColLocation empty)
|
||||
9 ColAssignedTo — Assigned to
|
||||
10 ColStatus — Status
|
||||
11 — — Column 1 (junk, ignored)
|
||||
12 — — Campus duplicate (ignored)
|
||||
13 ColNotes — Notes
|
||||
14 — — Category (ignored)
|
||||
15 — — Resolution Confirmed (ignored)
|
||||
ColCompletionDate = -1 (no dedicated column; disabled)
|
||||
```
|
||||
|
||||
Set any index to `-1` to disable it. `SafeGet()` returns null for index < 0.
|
||||
|
||||
## Sidebar Bucket Logic
|
||||
|
||||
Buckets are evaluated in priority order and are mutually exclusive:
|
||||
|
||||
```csharp
|
||||
rfr = status contains "ready for return" OR "ready for pickup"
|
||||
onHold = status contains "on hold" AND NOT in rfr
|
||||
awaitingVendor= status contains "awaiting vendor" AND NOT in rfr, onHold
|
||||
awaitingParts = status contains "awaiting parts" AND NOT in rfr, onHold, awaitingVendor
|
||||
main = everything else
|
||||
```
|
||||
|
||||
Status is checked against `StatusOverride ?? DiscoStatus`.
|
||||
|
||||
## NTT Closed Ticket Suppression
|
||||
|
||||
NTT tickets are skipped in `BuildDashboard` if their saved `StatusOverride` contains any of:
|
||||
`resolved, dismissed, complete, closed, done, cancel, finished`
|
||||
|
||||
This is independent of the sheet's own status column — it prevents jobs dismissed in the tracker from reappearing on every sheet refresh.
|
||||
|
||||
## Location Resolution for NTT Tiles
|
||||
|
||||
```
|
||||
ExternalTicket.Location (from ColLocation)
|
||||
└─ empty? → try ColCampus
|
||||
└─ still empty? → null
|
||||
|
||||
MatchSheetLocation(raw):
|
||||
1. Exact ID match against cfg.Locations
|
||||
2. Exact Name match (case-insensitive)
|
||||
3. Substring match either direction
|
||||
|
||||
Match found → use matched location (id/name/icon/colour)
|
||||
No match → use DefaultLocation + store raw in RawSheetLocation
|
||||
(displayed as italic 📍 pill on tile)
|
||||
|
||||
Saved LocationId override (from external_tickets/) always wins over sheet text.
|
||||
```
|
||||
|
||||
## HTML Generation Pattern
|
||||
|
||||
No Razor. Every page is a method returning `string` from a `StringBuilder`:
|
||||
- `BuildDashboardPage(DashboardViewModel)` — main dashboard
|
||||
- `BuildDetailPage(Job, ServiceTicket, ...)` — job detail + edit
|
||||
- `BuildConfigPage(ServiceTrackerConfig, ...)` — settings
|
||||
- `TileHtml(DashboardTile)` — single tile card
|
||||
- `SidebarPanel(title, color, items, url, showCollected)` — reusable sidebar section
|
||||
|
||||
CSS is returned from `CSS()`, `DCSS()`, `CCSS()` string methods and inlined in `<style>` tags. No external stylesheets.
|
||||
|
||||
## Cache Invalidation
|
||||
|
||||
`DashboardCache` watches file modification times on `config.json`, `external_tickets.json`, and the tickets directory. Any file change invalidates the cache. Cache key includes sortBy + filter string.
|
||||
|
||||
## Priority SLA Logic
|
||||
|
||||
Each `PriorityLevel` has a `SlaHours` value. SLA deadline = `job.OpenedDate + SlaHours`. Warning fires at 75% elapsed. `SlaHours = 0` means no SLA (used for "Scheduled" priority).
|
||||
Reference in new issue
Block a user