Offene Rechnungen anzeigen lassen.
This commit is contained in:
parent
fbe1b34b25
commit
57073ffc05
16
app.js
16
app.js
@ -73,7 +73,7 @@ app.use(express.json());
|
|||||||
app.use(
|
app.use(
|
||||||
helmet({
|
helmet({
|
||||||
contentSecurityPolicy: false,
|
contentSecurityPolicy: false,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
@ -83,7 +83,7 @@ app.use(
|
|||||||
store: getSessionStore(),
|
store: getSessionStore(),
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// ✅ i18n Middleware (SAFE)
|
// ✅ i18n Middleware (SAFE)
|
||||||
@ -156,7 +156,7 @@ app.use(async (req, res, next) => {
|
|||||||
`SELECT id, serial_number, trial_started_at
|
`SELECT id, serial_number, trial_started_at
|
||||||
FROM company_settings
|
FROM company_settings
|
||||||
ORDER BY id ASC
|
ORDER BY id ASC
|
||||||
LIMIT 1`
|
LIMIT 1`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const settings = rowsSettings?.[0];
|
const settings = rowsSettings?.[0];
|
||||||
@ -170,7 +170,7 @@ app.use(async (req, res, next) => {
|
|||||||
.promise()
|
.promise()
|
||||||
.query(
|
.query(
|
||||||
`UPDATE company_settings SET trial_started_at = NOW() WHERE id = ?`,
|
`UPDATE company_settings SET trial_started_at = NOW() WHERE id = ?`,
|
||||||
[settings.id]
|
[settings.id],
|
||||||
);
|
);
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ app.get("/serial-number", async (req, res) => {
|
|||||||
`SELECT id, serial_number, trial_started_at
|
`SELECT id, serial_number, trial_started_at
|
||||||
FROM company_settings
|
FROM company_settings
|
||||||
ORDER BY id ASC
|
ORDER BY id ASC
|
||||||
LIMIT 1`
|
LIMIT 1`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const settings = rowsSettings?.[0];
|
const settings = rowsSettings?.[0];
|
||||||
@ -240,7 +240,7 @@ app.get("/serial-number", async (req, res) => {
|
|||||||
.promise()
|
.promise()
|
||||||
.query(
|
.query(
|
||||||
`UPDATE company_settings SET trial_started_at = NOW() WHERE id = ?`,
|
`UPDATE company_settings SET trial_started_at = NOW() WHERE id = ?`,
|
||||||
[settings.id]
|
[settings.id],
|
||||||
);
|
);
|
||||||
settings.trial_started_at = new Date();
|
settings.trial_started_at = new Date();
|
||||||
}
|
}
|
||||||
@ -288,7 +288,7 @@ app.get("/admin/serial-number", async (req, res) => {
|
|||||||
const [rowsSettings] = await db
|
const [rowsSettings] = await db
|
||||||
.promise()
|
.promise()
|
||||||
.query(
|
.query(
|
||||||
`SELECT serial_number FROM company_settings ORDER BY id ASC LIMIT 1`
|
`SELECT serial_number FROM company_settings ORDER BY id ASC LIMIT 1`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const currentSerial = rowsSettings?.[0]?.serial_number || "";
|
const currentSerial = rowsSettings?.[0]?.serial_number || "";
|
||||||
@ -399,7 +399,7 @@ app.use("/services", serviceRoutes);
|
|||||||
|
|
||||||
app.use("/", patientFileRoutes);
|
app.use("/", patientFileRoutes);
|
||||||
app.use("/", waitingRoomRoutes);
|
app.use("/", waitingRoomRoutes);
|
||||||
app.use("/", invoiceRoutes);
|
app.use("/invoices", invoiceRoutes);
|
||||||
|
|
||||||
app.get("/logout", (req, res) => {
|
app.get("/logout", (req, res) => {
|
||||||
req.session.destroy(() => res.redirect("/"));
|
req.session.destroy(() => res.redirect("/"));
|
||||||
|
|||||||
33
controllers/invoice.controller.js
Normal file
33
controllers/invoice.controller.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const db = require("../db");
|
||||||
|
|
||||||
|
exports.openInvoices = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const [rows] = await db.promise().query(`
|
||||||
|
SELECT
|
||||||
|
i.id,
|
||||||
|
i.invoice_date,
|
||||||
|
i.total_amount,
|
||||||
|
i.status,
|
||||||
|
p.firstname,
|
||||||
|
p.lastname
|
||||||
|
FROM invoices i
|
||||||
|
JOIN patients p ON p.id = i.patient_id
|
||||||
|
WHERE i.status = 'open'
|
||||||
|
ORDER BY i.invoice_date DESC
|
||||||
|
`);
|
||||||
|
console.log("ROWS:", rows);
|
||||||
|
const invoices = rows.map((inv) => ({
|
||||||
|
...inv,
|
||||||
|
total_amount_formatted: Number(inv.total_amount).toFixed(2),
|
||||||
|
}));
|
||||||
|
|
||||||
|
res.render("invoices/open-invoices", {
|
||||||
|
user: req.session.user,
|
||||||
|
invoices,
|
||||||
|
active: "open_invoices",
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ openInvoices Fehler:", err);
|
||||||
|
res.status(500).send("Fehler beim Laden der offenen Rechnungen");
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -287,7 +287,7 @@ async function listOpenServices(req, res, next) {
|
|||||||
|
|
||||||
res.render("open_services", {
|
res.render("open_services", {
|
||||||
title: "Offene Leistungen",
|
title: "Offene Leistungen",
|
||||||
sidebarPartial: "partials/patient_sidebar",
|
sidebarPartial: "partials/sidebar-invoices",
|
||||||
active: "services",
|
active: "services",
|
||||||
|
|
||||||
rows,
|
rows,
|
||||||
|
|||||||
148
locales/de.json
148
locales/de.json
@ -6,55 +6,56 @@
|
|||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"dashboard": "Dashboard",
|
"dashboard": "Dashboard",
|
||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"title":"Titel",
|
"title": "Titel",
|
||||||
"firstname":"Vorname",
|
"firstname": "Vorname",
|
||||||
"lastname":"Nachname",
|
"lastname": "Nachname",
|
||||||
"username":"Username",
|
"username": "Username",
|
||||||
"role":"Rolle",
|
"role": "Rolle",
|
||||||
"action":"Aktionen",
|
"action": "Aktionen",
|
||||||
"status":"Status",
|
"status": "Status",
|
||||||
"you":"Du Selbst",
|
"you": "Du Selbst",
|
||||||
"newuser":"Neuer benutzer",
|
"newuser": "Neuer benutzer",
|
||||||
"inactive":"inaktive",
|
"inactive": "inaktive",
|
||||||
"active":"aktive",
|
"active": "aktive",
|
||||||
"closed":"gesperrt",
|
"closed": "gesperrt",
|
||||||
"filter":"Filtern",
|
"filter": "Filtern",
|
||||||
"yearcash":"Jahresumsatz",
|
"yearcash": "Jahresumsatz",
|
||||||
"monthcash":"Monatsumsatz",
|
"monthcash": "Monatsumsatz",
|
||||||
"quartalcash":"Quartalsumsatz",
|
"quartalcash": "Quartalsumsatz",
|
||||||
"year":"Jahr",
|
"year": "Jahr",
|
||||||
"nodata":"keine Daten",
|
"nodata": "keine Daten",
|
||||||
"month":"Monat",
|
"month": "Monat",
|
||||||
"patientcash":"Umsatz pro Patient",
|
"patientcash": "Umsatz pro Patient",
|
||||||
"patient":"Patient",
|
"patient": "Patient",
|
||||||
"systeminfo":"Systeminformationen",
|
"systeminfo": "Systeminformationen",
|
||||||
"table":"Tabelle",
|
"table": "Tabelle",
|
||||||
"lines":"Zeilen",
|
"lines": "Zeilen",
|
||||||
"size":"Grösse",
|
"size": "Grösse",
|
||||||
"errordatabase":"Fehler beim Auslesen der Datenbankinfos:",
|
"errordatabase": "Fehler beim Auslesen der Datenbankinfos:",
|
||||||
"welcome":"Willkommen",
|
"welcome": "Willkommen",
|
||||||
"waitingroomtext":"Wartezimmer-Monitor",
|
"waitingroomtext": "Wartezimmer-Monitor",
|
||||||
"waitingroomtextnopatient":"Keine Patienten im Wartezimmer.",
|
"waitingroomtextnopatient": "Keine Patienten im Wartezimmer.",
|
||||||
"gender":"Geschlecht",
|
"gender": "Geschlecht",
|
||||||
"birthday":"Geburtstag",
|
"birthday": "Geburtstag",
|
||||||
"email":"E-Mail",
|
"email": "E-Mail",
|
||||||
"phone":"Telefon",
|
"phone": "Telefon",
|
||||||
"address":"Adresse",
|
"address": "Adresse",
|
||||||
"country":"Land",
|
"country": "Land",
|
||||||
"notice":"Notizen",
|
"notice": "Notizen",
|
||||||
"create":"Erstellt",
|
"create": "Erstellt",
|
||||||
"change":"Geändert",
|
"change": "Geändert",
|
||||||
"reset2":"Zurücksetzen",
|
"reset2": "Zurücksetzen",
|
||||||
"edit":"Bearbeiten",
|
"edit": "Bearbeiten",
|
||||||
"selection":"Auswahl",
|
"selection": "Auswahl",
|
||||||
"waiting":"Wartet bereits",
|
"waiting": "Wartet bereits",
|
||||||
"towaitingroom":"Ins Wartezimmer",
|
"towaitingroom": "Ins Wartezimmer",
|
||||||
"overview":"Übersicht",
|
"overview": "Übersicht",
|
||||||
"upload":"Hochladen",
|
"upload": "Hochladen",
|
||||||
"lock":"Sperren",
|
"lock": "Sperren",
|
||||||
"unlock":"Enrsperren",
|
"unlock": "Enrsperren",
|
||||||
"name":"Name"
|
"name": "Name"
|
||||||
},
|
},
|
||||||
|
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"patients": "Patienten",
|
"patients": "Patienten",
|
||||||
"medications": "Medikamente",
|
"medications": "Medikamente",
|
||||||
@ -63,56 +64,61 @@
|
|||||||
"admin": "Verwaltung",
|
"admin": "Verwaltung",
|
||||||
"logout": "Logout"
|
"logout": "Logout"
|
||||||
},
|
},
|
||||||
|
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"welcome": "Willkommen",
|
"welcome": "Willkommen",
|
||||||
"waitingRoom": "Wartezimmer-Monitor",
|
"waitingRoom": "Wartezimmer-Monitor",
|
||||||
"noWaitingPatients": "Keine Patienten im Wartezimmer.",
|
"noWaitingPatients": "Keine Patienten im Wartezimmer.",
|
||||||
"title":"Dashboard"
|
"title": "Dashboard"
|
||||||
},
|
},
|
||||||
|
|
||||||
"adminSidebar": {
|
"adminSidebar": {
|
||||||
"users": "Userverwaltung",
|
"users": "Userverwaltung",
|
||||||
"database": "Datenbankverwaltung",
|
"database": "Datenbankverwaltung",
|
||||||
"user":"Benutzer",
|
"user": "Benutzer",
|
||||||
"invocieoverview":"Rechnungsübersicht",
|
"invocieoverview": "Rechnungsübersicht",
|
||||||
"seriennumber":"Seriennummer",
|
"seriennumber": "Seriennummer",
|
||||||
"databasetable":"Datenbank",
|
"databasetable": "Datenbank",
|
||||||
"companysettings":"Firmendaten"
|
"companysettings": "Firmendaten"
|
||||||
},
|
},
|
||||||
|
|
||||||
"adminuseroverview": {
|
"adminuseroverview": {
|
||||||
"useroverview": "Benutzerübersicht",
|
"useroverview": "Benutzerübersicht",
|
||||||
"usermanagement": "Benutzer Verwaltung",
|
"usermanagement": "Benutzer Verwaltung",
|
||||||
"user":"Benutzer",
|
"user": "Benutzer",
|
||||||
"invocieoverview":"Rechnungsübersicht",
|
"invocieoverview": "Rechnungsübersicht",
|
||||||
"seriennumber":"Seriennummer",
|
"seriennumber": "Seriennummer",
|
||||||
"databasetable":"Datenbank"
|
"databasetable": "Datenbank"
|
||||||
},
|
},
|
||||||
|
|
||||||
"seriennumber": {
|
"seriennumber": {
|
||||||
"seriennumbertitle": "Seriennummer eingeben",
|
"seriennumbertitle": "Seriennummer eingeben",
|
||||||
"seriennumbertext": "Bitte gib deine Lizenz-Seriennummer ein um die Software dauerhaft freizuschalten.",
|
"seriennumbertext": "Bitte gib deine Lizenz-Seriennummer ein um die Software dauerhaft freizuschalten.",
|
||||||
"seriennumbershort":"Seriennummer (AAAAA-AAAAA-AAAAA-AAAAA)",
|
"seriennumbershort": "Seriennummer (AAAAA-AAAAA-AAAAA-AAAAA)",
|
||||||
"seriennumberdeclaration":"Nur Buchstaben + Zahlen. Format: 4×5 Zeichen, getrennt mit „-“. ",
|
"seriennumberdeclaration": "Nur Buchstaben + Zahlen. Format: 4×5 Zeichen, getrennt mit „-“. ",
|
||||||
"saveseriennumber":"Seriennummer Speichern"
|
"saveseriennumber": "Seriennummer Speichern"
|
||||||
},
|
},
|
||||||
|
|
||||||
"databaseoverview": {
|
"databaseoverview": {
|
||||||
"title": "Datenbank Konfiguration",
|
"title": "Datenbank Konfiguration",
|
||||||
"text":"Hier kannst du die DB-Verbindung testen und speichern. ",
|
"text": "Hier kannst du die DB-Verbindung testen und speichern. ",
|
||||||
"host": "Host",
|
"host": "Host",
|
||||||
"port":"Port",
|
"port": "Port",
|
||||||
"database":"Datenbank",
|
"database": "Datenbank",
|
||||||
"password":"Password",
|
"password": "Password",
|
||||||
"connectiontest":"Verbindung testen",
|
"connectiontest": "Verbindung testen",
|
||||||
"tablecount":"Anzahl Tabellen",
|
"tablecount": "Anzahl Tabellen",
|
||||||
"databasesize":"Datenbankgrösse",
|
"databasesize": "Datenbankgrösse",
|
||||||
"tableoverview":"Tabellenübersicht"
|
"tableoverview": "Tabellenübersicht"
|
||||||
},
|
},
|
||||||
|
|
||||||
"patienteoverview": {
|
"patienteoverview": {
|
||||||
"patienttitle": "Patientenübersicht",
|
"patienttitle": "Patientenübersicht",
|
||||||
"newpatient":"Neuer Patient",
|
"newpatient": "Neuer Patient",
|
||||||
"nopatientfound":"Keine Patienten gefunden"
|
"nopatientfound": "Keine Patienten gefunden"
|
||||||
|
},
|
||||||
|
|
||||||
|
"openinvoices": {
|
||||||
|
"openinvoices": "Offene Rechnungen"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
147
locales/es.json
147
locales/es.json
@ -6,54 +6,54 @@
|
|||||||
"reset": "Resetear",
|
"reset": "Resetear",
|
||||||
"dashboard": "Panel",
|
"dashboard": "Panel",
|
||||||
"logout": "cerrar sesión",
|
"logout": "cerrar sesión",
|
||||||
"title":"Título",
|
"title": "Título",
|
||||||
"firstname":"Nombre",
|
"firstname": "Nombre",
|
||||||
"lastname":"apellido",
|
"lastname": "apellido",
|
||||||
"username":"Nombre de usuario",
|
"username": "Nombre de usuario",
|
||||||
"role":"desempeñar",
|
"role": "desempeñar",
|
||||||
"action":"acción",
|
"action": "acción",
|
||||||
"status":"Estado",
|
"status": "Estado",
|
||||||
"you":"su mismo",
|
"you": "su mismo",
|
||||||
"newuser":"Nuevo usuario",
|
"newuser": "Nuevo usuario",
|
||||||
"inactive":"inactivo",
|
"inactive": "inactivo",
|
||||||
"active":"activo",
|
"active": "activo",
|
||||||
"closed":"bloqueado",
|
"closed": "bloqueado",
|
||||||
"filter":"Filtro",
|
"filter": "Filtro",
|
||||||
"yearcash":"volumen de negocios anual",
|
"yearcash": "volumen de negocios anual",
|
||||||
"monthcash":"volumen de negocios mensual",
|
"monthcash": "volumen de negocios mensual",
|
||||||
"quartalcash":"volumen de negocios trimestral",
|
"quartalcash": "volumen de negocios trimestral",
|
||||||
"year":"ano",
|
"year": "ano",
|
||||||
"nodata":"sin datos",
|
"nodata": "sin datos",
|
||||||
"month":"mes",
|
"month": "mes",
|
||||||
"patientcash":"Ingresos por paciente",
|
"patientcash": "Ingresos por paciente",
|
||||||
"patient":"paciente",
|
"patient": "paciente",
|
||||||
"systeminfo":"Información del sistema",
|
"systeminfo": "Información del sistema",
|
||||||
"table":"tablas",
|
"table": "tablas",
|
||||||
"lines":"líneas",
|
"lines": "líneas",
|
||||||
"size":"Tamaño",
|
"size": "Tamaño",
|
||||||
"errordatabase":"Error al leer la información de la base de datos:",
|
"errordatabase": "Error al leer la información de la base de datos:",
|
||||||
"welcome":"Bienvenido",
|
"welcome": "Bienvenido",
|
||||||
"waitingroomtext":"Monitor de sala de espera",
|
"waitingroomtext": "Monitor de sala de espera",
|
||||||
"waitingroomtextnopatient":"No hay pacientes en la sala de espera.",
|
"waitingroomtextnopatient": "No hay pacientes en la sala de espera.",
|
||||||
"gender":"Sexo",
|
"gender": "Sexo",
|
||||||
"birthday":"Fecha de nacimiento",
|
"birthday": "Fecha de nacimiento",
|
||||||
"email":"Correo electrónico",
|
"email": "Correo electrónico",
|
||||||
"phone":"Teléfono",
|
"phone": "Teléfono",
|
||||||
"address":"Dirección",
|
"address": "Dirección",
|
||||||
"country":"País",
|
"country": "País",
|
||||||
"notice":"Notas",
|
"notice": "Notas",
|
||||||
"create":"Creado",
|
"create": "Creado",
|
||||||
"change":"Modificado",
|
"change": "Modificado",
|
||||||
"reset2":"Restablecer",
|
"reset2": "Restablecer",
|
||||||
"edit":"editar",
|
"edit": "editar",
|
||||||
"selection":"Selección",
|
"selection": "Selección",
|
||||||
"waiting":"Ya está esperando",
|
"waiting": "Ya está esperando",
|
||||||
"towaitingroom":"A la sala de espera",
|
"towaitingroom": "A la sala de espera",
|
||||||
"overview":"Resumen",
|
"overview": "Resumen",
|
||||||
"upload":"Cargar",
|
"upload": "Cargar",
|
||||||
"lock":"bloquear",
|
"lock": "bloquear",
|
||||||
"unlock":"desbloquear",
|
"unlock": "desbloquear",
|
||||||
"name":"Nombre"
|
"name": "Nombre"
|
||||||
},
|
},
|
||||||
|
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
@ -64,56 +64,61 @@
|
|||||||
"admin": "Administración",
|
"admin": "Administración",
|
||||||
"logout": "Cerrar sesión"
|
"logout": "Cerrar sesión"
|
||||||
},
|
},
|
||||||
|
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"welcome": "Bienvenido",
|
"welcome": "Bienvenido",
|
||||||
"waitingRoom": "Monitor sala de espera",
|
"waitingRoom": "Monitor sala de espera",
|
||||||
"noWaitingPatients": "No hay pacientes en la sala de espera.",
|
"noWaitingPatients": "No hay pacientes en la sala de espera.",
|
||||||
"title":"Dashboard"
|
"title": "Dashboard"
|
||||||
},
|
},
|
||||||
|
|
||||||
"adminSidebar": {
|
"adminSidebar": {
|
||||||
"users": "Administración de usuarios",
|
"users": "Administración de usuarios",
|
||||||
"database": "Administración de base de datos",
|
"database": "Administración de base de datos",
|
||||||
"user":"usuario",
|
"user": "usuario",
|
||||||
"invocieoverview":"Resumen de facturas",
|
"invocieoverview": "Resumen de facturas",
|
||||||
"seriennumber":"número de serie",
|
"seriennumber": "número de serie",
|
||||||
"databasetable":"base de datos",
|
"databasetable": "base de datos",
|
||||||
"companysettings":"Datos de la empresa"
|
"companysettings": "Datos de la empresa"
|
||||||
},
|
},
|
||||||
|
|
||||||
"adminuseroverview": {
|
"adminuseroverview": {
|
||||||
"useroverview": "Resumen de usuarios",
|
"useroverview": "Resumen de usuarios",
|
||||||
"usermanagement": "Administración de usuarios",
|
"usermanagement": "Administración de usuarios",
|
||||||
"user":"usuario",
|
"user": "usuario",
|
||||||
"invocieoverview":"Resumen de facturas",
|
"invocieoverview": "Resumen de facturas",
|
||||||
"seriennumber":"número de serie",
|
"seriennumber": "número de serie",
|
||||||
"databasetable":"base de datos"
|
"databasetable": "base de datos"
|
||||||
},
|
},
|
||||||
|
|
||||||
"seriennumber": {
|
"seriennumber": {
|
||||||
"seriennumbertitle": "Introduce el número de serie",
|
"seriennumbertitle": "Introduce el número de serie",
|
||||||
"seriennumbertext": "Introduce el número de serie de tu licencia para activar el software de forma permanente.",
|
"seriennumbertext": "Introduce el número de serie de tu licencia para activar el software de forma permanente.",
|
||||||
"seriennumbershort":"Número de serie (AAAAA-AAAAA-AAAAA-AAAAA)",
|
"seriennumbershort": "Número de serie (AAAAA-AAAAA-AAAAA-AAAAA)",
|
||||||
"seriennumberdeclaration":"Solo letras y números. Formato: 4×5 caracteres, separados por «-». ",
|
"seriennumberdeclaration": "Solo letras y números. Formato: 4×5 caracteres, separados por «-». ",
|
||||||
"saveseriennumber":"Guardar número de serie"
|
"saveseriennumber": "Guardar número de serie"
|
||||||
},
|
},
|
||||||
|
|
||||||
"databaseoverview": {
|
"databaseoverview": {
|
||||||
"title": "Configuración de la base de datos",
|
"title": "Configuración de la base de datos",
|
||||||
"host": "Host",
|
"host": "Host",
|
||||||
"port":"Puerto",
|
"port": "Puerto",
|
||||||
"database":"Base de datos",
|
"database": "Base de datos",
|
||||||
"password":"Contraseña",
|
"password": "Contraseña",
|
||||||
"connectiontest":"Probar conexión",
|
"connectiontest": "Probar conexión",
|
||||||
"text":"Aquí puedes probar y guardar la conexión a la base de datos. ",
|
"text": "Aquí puedes probar y guardar la conexión a la base de datos. ",
|
||||||
"tablecount":"Número de tablas",
|
"tablecount": "Número de tablas",
|
||||||
"databasesize":"Tamaño de la base de datos",
|
"databasesize": "Tamaño de la base de datos",
|
||||||
"tableoverview":"Resumen de tablas"
|
"tableoverview": "Resumen de tablas"
|
||||||
},
|
},
|
||||||
|
|
||||||
"patienteoverview": {
|
"patienteoverview": {
|
||||||
"patienttitle": "Resumen de pacientes",
|
"patienttitle": "Resumen de pacientes",
|
||||||
"newpatient":"Paciente nuevo",
|
"newpatient": "Paciente nuevo",
|
||||||
"nopatientfound":"No se han encontrado pacientes."
|
"nopatientfound": "No se han encontrado pacientes."
|
||||||
|
},
|
||||||
|
|
||||||
|
"openinvoices": {
|
||||||
|
"openinvoices": "Facturas pendientes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
const { requireArzt } = require("../middleware/auth.middleware");
|
const { requireArzt } = require("../middleware/auth.middleware");
|
||||||
const { createInvoicePdf } = require("../controllers/invoicePdf.controller");
|
const { createInvoicePdf } = require("../controllers/invoicePdf.controller");
|
||||||
|
const { openInvoices } = require("../controllers/invoice.controller");
|
||||||
|
|
||||||
|
// ✅ NEU: Offene Rechnungen anzeigen
|
||||||
|
router.get("/open", requireArzt, openInvoices);
|
||||||
|
|
||||||
|
// Bestehend
|
||||||
router.post("/patients/:id/create-invoice", requireArzt, createInvoicePdf);
|
router.post("/patients/:id/create-invoice", requireArzt, createInvoicePdf);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
28
views/invoices/open-invoices.ejs
Normal file
28
views/invoices/open-invoices.ejs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<h1>🧾 Offene Rechnungen</h1>
|
||||||
|
|
||||||
|
<% if (invoices.length === 0) { %>
|
||||||
|
<p>Keine offenen Rechnungen 🎉</p>
|
||||||
|
<% } else { %>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Patient</th>
|
||||||
|
<th>Datum</th>
|
||||||
|
<th>Betrag</th>
|
||||||
|
<th>Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% invoices.forEach(inv => { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= inv.id %></td>
|
||||||
|
<td><%= inv.firstname %> <%= inv.lastname %></td>
|
||||||
|
<td><%= inv.invoice_date %></td>
|
||||||
|
<td><%= inv.total_amount_formatted %> €</td>
|
||||||
|
<td>offen</td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<% } %>
|
||||||
@ -1,36 +0,0 @@
|
|||||||
<div class="sidebar">
|
|
||||||
<div class="logo">
|
|
||||||
<i class="bi bi-cash-coin"></i>
|
|
||||||
Invoice Menü
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="/admin/invoices?view=year"
|
|
||||||
class="nav-item <%= active === 'sales_year' ? 'active' : '' %>"
|
|
||||||
>
|
|
||||||
<i class="bi bi-calendar3"></i> <%= t.adminInvoice.annualSales %>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="/admin/invoices?view=quarter"
|
|
||||||
class="nav-item <%= active === 'sales_quarter' ? 'active' : '' %>"
|
|
||||||
>
|
|
||||||
<i class="bi bi-calendar2-week"></i> <%= t.adminInvoice.quarterlySales %>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="/admin/invoices?view=month"
|
|
||||||
class="nav-item <%= active === 'sales_month' ? 'active' : '' %>"
|
|
||||||
>
|
|
||||||
<i class="bi bi-calendar2"></i> <%= t.adminInvoice.monthSales %>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a
|
|
||||||
href="/admin/invoices?view=patient"
|
|
||||||
class="nav-item <%= active === 'sales_patient' ? 'active' : '' %>"
|
|
||||||
>
|
|
||||||
<i class="bi bi-people"></i> <%= t.adminInvoice.patientsSales %>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<div class="spacer"></div>
|
|
||||||
</div>
|
|
||||||
@ -167,10 +167,6 @@
|
|||||||
<% } %>
|
<% } %>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="sidebar-muted" style="margin-top: 6px">
|
|
||||||
Nur aktiv nach Patientenauswahl
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% if (canUsePatient) { %>
|
<% if (canUsePatient) { %>
|
||||||
</form>
|
</form>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
// BASISDATEN
|
// BASISDATEN
|
||||||
// =========================
|
// =========================
|
||||||
const role = user?.role || null;
|
const role = user?.role || null;
|
||||||
|
// ✅ Bereich 1: Arzt + Mitarbeiter
|
||||||
|
const canDoctorAndStaff = role === "arzt" || role === "mitarbeiter";
|
||||||
|
|
||||||
// Arzt + Mitarbeiter dürfen Patienten bedienen
|
// Arzt + Mitarbeiter dürfen Patienten bedienen
|
||||||
const canPatientArea = role === "arzt" || role === "mitarbeiter";
|
const canPatientArea = role === "arzt" || role === "mitarbeiter";
|
||||||
@ -38,28 +40,21 @@
|
|||||||
|
|
||||||
<div style="margin:10px 0; border-top:1px solid rgba(255,255,255,0.12);"></div>
|
<div style="margin:10px 0; border-top:1px solid rgba(255,255,255,0.12);"></div>
|
||||||
|
|
||||||
<!-- ✅ Kein Patient gewählt -->
|
|
||||||
<% if (!pid) { %>
|
|
||||||
<div class="nav-item locked" style="opacity:0.7;">
|
|
||||||
<i class="bi bi-info-circle"></i> Bitte Patient auswählen
|
|
||||||
<span style="margin-left:auto;"><i class="bi bi-lock-fill"></i></span>
|
|
||||||
</div>
|
|
||||||
<% } %>
|
|
||||||
|
|
||||||
<!-- =========================
|
<!-- =========================
|
||||||
Rechnungen
|
Rechnungen
|
||||||
========================= -->
|
========================= -->
|
||||||
<a
|
<a
|
||||||
href="<%= hrefIfAllowed(canDoctorAndStaff, '/patients') %>"
|
href="<%= hrefIfAllowed(canDoctorAndStaff, '/invoices/open') %>"
|
||||||
class="nav-item <%= active === 'patients' ? 'active' : '' %> <%= lockClass(canDoctorAndStaff) %>"
|
class="nav-item <%= active === 'open_invoices' ? 'active' : '' %> <%= lockClass(canDoctorAndStaff) %>"
|
||||||
title="<%= canDoctorAndStaff ? '' : 'Nur Arzt + Mitarbeiter' %>"
|
title="<%= canDoctorAndStaff ? '' : 'Nur Arzt + Mitarbeiter' %>"
|
||||||
>
|
>
|
||||||
<i class="bi bi-people"></i> <%= t.sidebar.patients %>
|
<i class="bi bi-receipt"></i> <%= t.openinvoices.openinvoices %>
|
||||||
<% if (!canDoctorAndStaff) { %>
|
<% if (!canDoctorAndStaff) { %>
|
||||||
<span style="margin-left:auto;"><i class="bi bi-lock-fill"></i></span>
|
<span style="margin-left:auto;"><i class="bi bi-lock-fill"></i></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<a
|
<a
|
||||||
href="<%= hrefIfAllowed(canDoctorAndStaff, '/patients') %>"
|
href="<%= hrefIfAllowed(canDoctorAndStaff, '/patients') %>"
|
||||||
class="nav-item <%= active === 'patients' ? 'active' : '' %> <%= lockClass(canDoctorAndStaff) %>"
|
class="nav-item <%= active === 'patients' ? 'active' : '' %> <%= lockClass(canDoctorAndStaff) %>"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user