feat(ticket-module): Implement ticket system with comprehensive database schema, permissions, and testing suite
- Added migration 025 for the Ticket System, creating tables for tickets, comments, attachments, worklogs, prepaid cards, and audit logs.
- Introduced migration 026 to add ticket-related permissions to the auth system and assign them to user groups.
- Developed a test suite for the Ticket Module, validating database schema, ticket number generation, prepaid card constraints, service logic, worklog creation, audit logging, and views.
2025-12-15 23:40:23 +01:00
{% extends "shared/frontend/base.html" %}
{% block title %}Concept 1: Split Screen - BMC Hub{% endblock %}
{% block extra_css %}
< style >
/* Hide default footer if exists to maximize height */
footer { display: none; }
.split-layout {
display: flex;
height: 100%;
}
/* Left Sidebar: Ticket List */
.ticket-list-sidebar {
width: 350px;
flex-shrink: 0;
border-right: 1px solid rgba(0,0,0,0.1);
background: var(--bg-card);
display: flex;
flex-direction: column;
}
.list-header {
padding: 1rem;
border-bottom: 1px solid rgba(0,0,0,0.05);
}
.ticket-list-scroll {
overflow-y: auto;
flex-grow: 1;
}
.ticket-item {
padding: 1rem;
border-bottom: 1px solid rgba(0,0,0,0.05);
cursor: pointer;
transition: background-color 0.2s;
position: relative;
}
.ticket-item:hover {
background-color: var(--accent-light);
}
.ticket-item.active {
background-color: var(--accent-light);
border-left: 4px solid var(--accent);
}
.ticket-item.unread::after {
content: '';
position: absolute;
top: 1rem;
right: 1rem;
width: 8px;
height: 8px;
background-color: var(--accent);
border-radius: 50%;
}
/* Right Content: Detail View */
.ticket-detail-main {
flex-grow: 1;
background: var(--bg-body);
display: flex;
flex-direction: column;
overflow: hidden;
}
.detail-header {
background: var(--bg-card);
padding: 1rem 1.5rem;
border-bottom: 1px solid rgba(0,0,0,0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.detail-scroll {
flex-grow: 1;
overflow-y: auto;
padding: 1.5rem;
}
.detail-footer {
background: var(--bg-card);
padding: 1rem 1.5rem;
border-top: 1px solid rgba(0,0,0,0.1);
}
/* Chat bubbles */
.message-bubble {
background: var(--bg-card);
padding: 1rem;
border-radius: 12px;
margin-bottom: 1rem;
box-shadow: 0 1px 3px rgba(0,0,0,0.05);
max-width: 85%;
}
.message-bubble.internal {
2026-10-08 08:58:02 +02:00
background: var(--theme-warning-bg, #fff3cd);
feat(ticket-module): Implement ticket system with comprehensive database schema, permissions, and testing suite
- Added migration 025 for the Ticket System, creating tables for tickets, comments, attachments, worklogs, prepaid cards, and audit logs.
- Introduced migration 026 to add ticket-related permissions to the auth system and assign them to user groups.
- Developed a test suite for the Ticket Module, validating database schema, ticket number generation, prepaid card constraints, service logic, worklog creation, audit logging, and views.
2025-12-15 23:40:23 +01:00
border: 1px solid #ffeeba;
}
.message-bubble.me {
background: var(--accent-light);
margin-left: auto;
}
.meta-text {
font-size: 0.75rem;
color: var(--text-secondary);
margin-bottom: 0.25rem;
}
< / style >
{% endblock %}
{% block content_wrapper %}
< div class = "container-fluid p-0" style = "height: calc(100vh - 80px); overflow: hidden;" >
< div class = "split-layout" >
<!-- Left Sidebar -->
< div class = "ticket-list-sidebar" >
< div class = "list-header" >
< div class = "input-group" >
< span class = "input-group-text bg-transparent border-end-0" > < i class = "bi bi-search" > < / i > < / span >
< input type = "text" class = "form-control border-start-0" placeholder = "Søg tickets..." >
< / div >
< div class = "d-flex gap-2 mt-2 overflow-auto pb-1" >
< span class = "badge bg-primary rounded-pill" > Alle< / span >
< span class = "badge bg-light text-dark border rounded-pill" > Mine< / span >
< span class = "badge bg-light text-dark border rounded-pill" > Uløste< / span >
< / div >
< / div >
< div class = "ticket-list-scroll" >
<!-- Active Item -->
< div class = "ticket-item active" >
< div class = "d-flex justify-content-between mb-1" >
< span class = "badge bg-warning text-dark" > Høj< / span >
< small class = "text-muted" > 14:32< / small >
< / div >
< h6 class = "mb-1 text-truncate" > Netværksproblem i hovedkontoret< / h6 >
< div class = "d-flex align-items-center gap-2" >
< img src = "https://ui-avatars.com/api/?name=Tech+Corp&background=random" class = "rounded-circle" width = "20" >
< small class = "text-muted" > Tech Corp A/S< / small >
< / div >
< / div >
<!-- Other Items -->
< div class = "ticket-item unread" >
< div class = "d-flex justify-content-between mb-1" >
< span class = "badge bg-info text-white" > Ny< / span >
< small class = "text-muted" > 12:15< / small >
< / div >
< h6 class = "mb-1 text-truncate" > Printer løbet tør for toner< / h6 >
< div class = "d-flex align-items-center gap-2" >
< img src = "https://ui-avatars.com/api/?name=Advokat+Huset&background=random" class = "rounded-circle" width = "20" >
< small class = "text-muted" > Advokathuset< / small >
< / div >
< / div >
< div class = "ticket-item" >
< div class = "d-flex justify-content-between mb-1" >
< span class = "badge bg-success" > Løst< / span >
< small class = "text-muted" > I går< / small >
< / div >
< h6 class = "mb-1 text-truncate" > Opsætning af ny bruger (Mette)< / h6 >
< div class = "d-flex align-items-center gap-2" >
< img src = "https://ui-avatars.com/api/?name=Byg+Aps&background=random" class = "rounded-circle" width = "20" >
< small class = "text-muted" > Byg ApS< / small >
< / div >
< / div >
<!-- More dummy items -->
{% for i in range(5) %}
< div class = "ticket-item" >
< div class = "d-flex justify-content-between mb-1" >
< span class = "badge bg-secondary" > Venter< / span >
< small class = "text-muted" > 2 dage siden< / small >
< / div >
< h6 class = "mb-1 text-truncate" > Licens fornyelse Office 365< / h6 >
< div class = "d-flex align-items-center gap-2" >
< img src = "https://ui-avatars.com/api/?name=Kunde+{{i}}&background=random" class = "rounded-circle" width = "20" >
< small class = "text-muted" > Kunde {{i}}< / small >
< / div >
< / div >
{% endfor %}
< / div >
< / div >
<!-- Right Content -->
< div class = "ticket-detail-main" >
< div class = "detail-header" >
< div >
< div class = "d-flex align-items-center gap-2 mb-1" >
< span class = "badge bg-light text-dark border" > #TKT-20251215-005< / span >
< span class = "badge bg-warning text-dark" > I Gang< / span >
< / div >
< h5 class = "mb-0" > Netværksproblem i hovedkontoret< / h5 >
< / div >
< div class = "d-flex gap-2" >
< button class = "btn btn-outline-secondary btn-sm" > < i class = "bi bi-person-plus" > < / i > Tildel< / button >
< button class = "btn btn-outline-secondary btn-sm" > < i class = "bi bi-clock" > < / i > Log Tid< / button >
< button class = "btn btn-primary btn-sm" > < i class = "bi bi-check-lg" > < / i > Løs Sag< / button >
< / div >
< / div >
< div class = "detail-scroll" >
<!-- Original Request -->
< div class = "message-bubble" >
< div class = "d-flex justify-content-between align-items-center mb-2" >
< div class = "d-flex align-items-center gap-2" >
< img src = "https://ui-avatars.com/api/?name=Jens+Jensen&background=random" class = "rounded-circle" width = "24" >
< span class = "fw-bold" > Jens Jensen< / span >
< span class = "text-muted small" > via Email< / span >
< / div >
< small class = "text-muted" > 15. dec 14:32< / small >
< / div >
< p class = "mb-0" > Hej Support,< br > < br > Vi har problemer med internettet på hovedkontoret. Ingen kan komme på Wi-Fi, og kablet forbindelse virker heller ikke. Det haster meget!< / p >
< / div >
<!-- Internal Note -->
< div class = "message-bubble internal" >
< div class = "d-flex justify-content-between align-items-center mb-2" >
< div class = "d-flex align-items-center gap-2" >
< i class = "bi bi-shield-lock text-warning" > < / i >
< span class = "fw-bold text-warning-emphasis" > Intern Note< / span >
< / div >
< small class = "text-muted" > 15. dec 14:45< / small >
< / div >
< p class = "mb-0" > Jeg har tjekket Unifi controlleren. Switch #3 svarer ikke. Det er nok den der er nede.< / p >
< / div >
<!-- Reply -->
< div class = "message-bubble me" >
< div class = "d-flex justify-content-between align-items-center mb-2" >
< div class = "d-flex align-items-center gap-2" >
< img src = "https://ui-avatars.com/api/?name=Christian&background=0f4c75&color=fff" class = "rounded-circle" width = "24" >
< span class = "fw-bold" > Christian (Support)< / span >
< / div >
< small class = "text-muted" > 15. dec 14:50< / small >
< / div >
< p class = "mb-0" > Hej Jens,< br > < br > Jeg kigger på det med det samme. Jeg kan se vi har mistet forbindelsen til en af jeres switche. Jeg prøver at genstarte den remote.< / p >
< / div >
< / div >
< div class = "detail-footer" >
< div class = "input-group" >
< button class = "btn btn-outline-secondary" type = "button" > < i class = "bi bi-paperclip" > < / i > < / button >
< button class = "btn btn-outline-secondary dropdown-toggle" type = "button" data-bs-toggle = "dropdown" > Svar Kunde< / button >
< ul class = "dropdown-menu" >
< li > < a class = "dropdown-item" href = "#" > Svar Kunde< / a > < / li >
< li > < a class = "dropdown-item" href = "#" > < i class = "bi bi-shield-lock text-warning" > < / i > Intern Note< / a > < / li >
< / ul >
< input type = "text" class = "form-control" placeholder = "Skriv et svar..." >
< button class = "btn btn-primary" type = "button" > < i class = "bi bi-send" > < / i > Send< / button >
< / div >
< / div >
< / div >
< / div >
< / div >
{% endblock %}