Files
cv-site/doc/_go-learning/diagrams/05-data-models.md
T
juanatsap d95c62bad4 refactor: remove outdated server design documentation
Remove 557-line server-design.md from _go-learning/architecture - content is now covered in updated architecture documentation with real implementation examples and test coverage.
2025-12-02 20:25:05 +00:00

26 KiB

Data Models Diagram

Data Model Overview

┌──────────────────────────────────────────────────────────────┐
│                    Data Model Structure                       │
└──────────────────────────────────────────────────────────────┘

internal/models/
    ├── cv/          CV data structures
    │   ├── cv.go                Main CV model
    │   ├── personal.go          Personal information
    │   ├── experience.go        Work experience
    │   ├── education.go         Education history
    │   ├── skills.go            Technical skills
    │   └── languages.go         Language proficiency
    │
    └── ui/          UI text structures
        ├── ui.go                Main UI model
        ├── sections.go          Section titles
        ├── buttons.go           Button labels
        └── messages.go          User messages

CV Data Model

┌──────────────────────────────────────────────────────────────┐
│                     CV Structure (cv/cv.go)                   │
├──────────────────────────────────────────────────────────────┤
│  type CV struct {                                             │
│      Personal    Personal      `json:"personal"`              │
│      Summary     string        `json:"summary"`               │
│      Experience  []Experience  `json:"experience"`            │
│      Education   []Education   `json:"education"`             │
│      Skills      Skills        `json:"skills"`                │
│      Languages   []Language    `json:"languages"`             │
│  }                                                            │
│                                                               │
│  Methods:                                                     │
│  ├─ LoadCV(lang string) (*CV, error)                         │
│  │   └─→ Read data/cv-{lang}.json                            │
│  │                                                            │
│  ├─ Validate() error                                          │
│  │   └─→ Ensure all required fields present                  │
│  │                                                            │
│  └─ CalculateDurations()                                      │
│      └─→ Calculate years/months for experiences              │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│              Personal Information (cv/personal.go)            │
├──────────────────────────────────────────────────────────────┤
│  type Personal struct {                                       │
│      Name        string   `json:"name"`                       │
│      Title       string   `json:"title"`                      │
│      Email       string   `json:"email"`                      │
│      Phone       string   `json:"phone,omitempty"`            │
│      Location    string   `json:"location"`                   │
│      Website     string   `json:"website,omitempty"`          │
│      LinkedIn    string   `json:"linkedin,omitempty"`         │
│      GitHub      string   `json:"github,omitempty"`           │
│      Photo       string   `json:"photo,omitempty"`            │
│  }                                                            │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│             Work Experience (cv/experience.go)                │
├──────────────────────────────────────────────────────────────┤
│  type Experience struct {                                     │
│      Company     string   `json:"company"`                    │
│      Position    string   `json:"position"`                   │
│      Location    string   `json:"location"`                   │
│      StartDate   string   `json:"start_date"`                 │
│      EndDate     string   `json:"end_date,omitempty"`         │
│      Current     bool     `json:"current"`                    │
│      Description string   `json:"description"`                │
│      Highlights  []string `json:"highlights"`                 │
│      Duration    string   `json:"-"`  // Calculated          │
│  }                                                            │
│                                                               │
│  Methods:                                                     │
│  ├─ CalculateDuration() string                                │
│  │   ├─ Parse StartDate and EndDate                          │
│  │   ├─ Calculate difference                                 │
│  │   └─ Return: "2 years 3 months" or "Present"             │
│  │                                                            │
│  └─ IsCurrent() bool                                          │
│      └─→ Check if EndDate is empty or Current flag           │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│                Education (cv/education.go)                    │
├──────────────────────────────────────────────────────────────┤
│  type Education struct {                                      │
│      Institution string   `json:"institution"`                │
│      Degree      string   `json:"degree"`                     │
│      Field       string   `json:"field"`                      │
│      Location    string   `json:"location"`                   │
│      StartDate   string   `json:"start_date"`                 │
│      EndDate     string   `json:"end_date,omitempty"`         │
│      GPA         string   `json:"gpa,omitempty"`              │
│      Honors      []string `json:"honors,omitempty"`           │
│  }                                                            │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│                  Skills (cv/skills.go)                        │
├──────────────────────────────────────────────────────────────┤
│  type Skills struct {                                         │
│      Technical   []Skill `json:"technical"`                   │
│      Soft        []Skill `json:"soft"`                        │
│      Tools       []Skill `json:"tools"`                       │
│  }                                                            │
│                                                               │
│  type Skill struct {                                          │
│      Name        string   `json:"name"`                       │
│      Level       string   `json:"level,omitempty"`            │
│      Icon        string   `json:"icon,omitempty"`             │
│      Category    string   `json:"category,omitempty"`         │
│  }                                                            │
│                                                               │
│  Methods:                                                     │
│  └─ SplitIntoColumns(numCols int) [][]Skill                   │
│      └─→ Distribute skills evenly across columns             │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│                Languages (cv/languages.go)                    │
├──────────────────────────────────────────────────────────────┤
│  type Language struct {                                       │
│      Name        string   `json:"name"`                       │
│      Level       string   `json:"level"`                      │
│      Proficiency string   `json:"proficiency,omitempty"`      │
│  }                                                            │
│                                                               │
│  Levels: Native, Fluent, Professional, Intermediate, Basic   │
└──────────────────────────────────────────────────────────────┘

UI Data Model

┌──────────────────────────────────────────────────────────────┐
│                    UI Structure (ui/ui.go)                    │
├──────────────────────────────────────────────────────────────┤
│  type UI struct {                                             │
│      Sections    Sections    `json:"sections"`                │
│      Buttons     Buttons     `json:"buttons"`                 │
│      Messages    Messages    `json:"messages"`                │
│      Labels      Labels      `json:"labels"`                  │
│  }                                                            │
│                                                               │
│  Methods:                                                     │
│  └─ LoadUI(lang string) (*UI, error)                         │
│      └─→ Read data/ui-{lang}.json                            │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│              Section Titles (ui/sections.go)                  │
├──────────────────────────────────────────────────────────────┤
│  type Sections struct {                                       │
│      Summary     string `json:"summary"`                      │
│      Experience  string `json:"experience"`                   │
│      Education   string `json:"education"`                    │
│      Skills      string `json:"skills"`                       │
│      Languages   string `json:"languages"`                    │
│      Contact     string `json:"contact"`                      │
│  }                                                            │
│                                                               │
│  Example (English):                                           │
│  {                                                            │
│    "summary": "Professional Summary",                        │
│    "experience": "Work Experience",                          │
│    "education": "Education",                                 │
│    "skills": "Technical Skills",                             │
│    "languages": "Languages",                                 │
│    "contact": "Contact Information"                          │
│  }                                                            │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│               Button Labels (ui/buttons.go)                   │
├──────────────────────────────────────────────────────────────┤
│  type Buttons struct {                                        │
│      ExportPDF      string `json:"export_pdf"`                │
│      ToggleLength   string `json:"toggle_length"`             │
│      ToggleIcons    string `json:"toggle_icons"`              │
│      ToggleTheme    string `json:"toggle_theme"`              │
│      ToggleLanguage string `json:"toggle_language"`           │
│      Print          string `json:"print"`                     │
│  }                                                            │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│              User Messages (ui/messages.go)                   │
├──────────────────────────────────────────────────────────────┤
│  type Messages struct {                                       │
│      Loading        string `json:"loading"`                   │
│      Error          string `json:"error"`                     │
│      Success        string `json:"success"`                   │
│      PDFGenerating  string `json:"pdf_generating"`            │
│      PDFReady       string `json:"pdf_ready"`                 │
│  }                                                            │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│                  Labels (ui/labels.go)                        │
├──────────────────────────────────────────────────────────────┤
│  type Labels struct {                                         │
│      ShortCV   string `json:"short_cv"`                       │
│      LongCV    string `json:"long_cv"`                        │
│      ShowIcons string `json:"show_icons"`                     │
│      HideIcons string `json:"hide_icons"`                     │
│      Light     string `json:"light"`                          │
│      Dark      string `json:"dark"`                           │
│  }                                                            │
└──────────────────────────────────────────────────────────────┘

Data Flow

┌────────────────────────────────────────────────────────────┐
│                      Data Flow                              │
└────────────────────────────────────────────────────────────┘

JSON Files (data/)
    ├── cv-en.json    English CV data
    ├── cv-es.json    Spanish CV data
    ├── ui-en.json    English UI strings
    └── ui-es.json    Spanish UI strings
         │
         ▼
┌─────────────────────────┐
│  LoadCV(lang)           │
│  LoadUI(lang)           │
│  (internal/models/)     │
└─────────────────────────┘
         │
         ├─→ Parse JSON
         ├─→ Validate structure
         └─→ Return typed structs
         │
         ▼
┌─────────────────────────┐
│  Handler                │
│  (internal/handlers/)   │
└─────────────────────────┐
         │
         ├─→ Calculate durations
         ├─→ Split skills
         └─→ Build template data map
         │
         ▼
┌─────────────────────────┐
│  Template Rendering     │
│  (templates/)           │
└─────────────────────────┘
         │
         ▼
    HTML Response

Example Data Structure

┌────────────────────────────────────────────────────────────┐
│              Sample CV Data (data/cv-en.json)              │
└────────────────────────────────────────────────────────────┘

{
  "personal": {
    "name": "John Doe",
    "title": "Senior Software Engineer",
    "email": "john@example.com",
    "location": "San Francisco, CA",
    "linkedin": "linkedin.com/in/johndoe",
    "github": "github.com/johndoe"
  },
  "summary": "Experienced software engineer with 8+ years...",
  "experience": [
    {
      "company": "Tech Corp",
      "position": "Senior Software Engineer",
      "location": "San Francisco, CA",
      "start_date": "2020-01",
      "end_date": "",
      "current": true,
      "description": "Leading backend development...",
      "highlights": [
        "Designed and implemented microservices architecture",
        "Reduced API response time by 60%",
        "Mentored 5 junior developers"
      ]
    }
  ],
  "education": [
    {
      "institution": "University of California",
      "degree": "Bachelor of Science",
      "field": "Computer Science",
      "location": "Berkeley, CA",
      "start_date": "2012-09",
      "end_date": "2016-05",
      "gpa": "3.8/4.0"
    }
  ],
  "skills": {
    "technical": [
      {"name": "Go", "level": "Expert", "icon": "golang"},
      {"name": "JavaScript", "level": "Advanced", "icon": "js"},
      {"name": "Python", "level": "Intermediate", "icon": "python"}
    ],
    "tools": [
      {"name": "Docker", "icon": "docker"},
      {"name": "Kubernetes", "icon": "k8s"},
      {"name": "Git", "icon": "git"}
    ]
  },
  "languages": [
    {"name": "English", "level": "Native"},
    {"name": "Spanish", "level": "Fluent"}
  ]
}

┌────────────────────────────────────────────────────────────┐
│              Sample UI Data (data/ui-en.json)              │
└────────────────────────────────────────────────────────────┘

{
  "sections": {
    "summary": "Professional Summary",
    "experience": "Work Experience",
    "education": "Education",
    "skills": "Technical Skills",
    "languages": "Languages"
  },
  "buttons": {
    "export_pdf": "Export PDF",
    "toggle_length": "Toggle Length",
    "toggle_icons": "Toggle Icons",
    "toggle_theme": "Toggle Theme",
    "toggle_language": "Switch Language"
  },
  "messages": {
    "loading": "Loading...",
    "error": "An error occurred",
    "pdf_generating": "Generating PDF...",
    "pdf_ready": "PDF is ready for download"
  },
  "labels": {
    "short_cv": "Short",
    "long_cv": "Long",
    "show_icons": "Show Icons",
    "hide_icons": "Hide Icons"
  }
}

Data Validation

┌────────────────────────────────────────────────────────────┐
│                    Validation Rules                         │
└────────────────────────────────────────────────────────────┘

CV Validation:
├─ Personal
│  ├─ Name: Required, non-empty
│  ├─ Title: Required, non-empty
│  ├─ Email: Required, valid email format
│  └─ Location: Required, non-empty
│
├─ Experience
│  ├─ Company: Required, non-empty
│  ├─ Position: Required, non-empty
│  ├─ StartDate: Required, valid date (YYYY-MM)
│  └─ EndDate: Optional, must be after StartDate if present
│
├─ Education
│  ├─ Institution: Required, non-empty
│  ├─ Degree: Required, non-empty
│  └─ Field: Required, non-empty
│
├─ Skills
│  ├─ Name: Required, non-empty
│  └─ Level: Optional, one of [Basic, Intermediate, Advanced, Expert]
│
└─ Languages
   ├─ Name: Required, non-empty
   └─ Level: Required, one of [Native, Fluent, Professional, Intermediate, Basic]

UI Validation:
├─ All section titles: Required, non-empty
├─ All button labels: Required, non-empty
└─ All messages: Required, non-empty

Model Lifecycle

┌────────────────────────────────────────────────────────────┐
│                    Model Lifecycle                          │
└────────────────────────────────────────────────────────────┘

Application Start
     │
     └─→ Models NOT loaded (lazy loading)
         │
         ▼
Request Arrives (lang=es)
     │
     ├─→ Handler calls LoadCV("es")
     │   ├─ Check cache (if caching enabled)
     │   ├─ Read data/cv-es.json
     │   ├─ Parse JSON → CV struct
     │   ├─ Validate struct
     │   └─ Return *CV
     │
     ├─→ Handler calls LoadUI("es")
     │   ├─ Read data/ui-es.json
     │   ├─ Parse JSON → UI struct
     │   └─ Return *UI
     │
     └─→ Handler processes data
         ├─ Calculate durations
         ├─ Split skills
         └─ Render template

Next Request (lang=es)
     │
     └─→ Models reloaded (no persistent cache)
         (Each request loads fresh data for hot reload)

Data Transformation

┌────────────────────────────────────────────────────────────┐
│               Data Transformation Pipeline                  │
└────────────────────────────────────────────────────────────┘

JSON (static)
     │
     ├─ "start_date": "2020-01"
     └─ "end_date": ""
         │
         ▼
Go Struct (typed)
     │
     ├─ StartDate: "2020-01"
     ├─ EndDate: ""
     └─ Duration: "" (empty)
         │
         ▼
Calculate Duration
     │
     ├─ Parse dates
     ├─ Calculate difference
     └─ Format: "3 years 2 months"
         │
         ▼
Template Data (enriched)
     │
     ├─ StartDate: "2020-01"
     ├─ EndDate: "Present"
     └─ Duration: "3 years 2 months"
         │
         ▼
HTML (rendered)
     │
     └─ <span class="duration">3 years 2 months</span>