107 lines
4.3 KiB
JavaScript
107 lines
4.3 KiB
JavaScript
import { config } from '../config.js'
|
||
import { berlinDateTime } from './berlinTime.js'
|
||
import { listDocuments, Query } from './appwriteAdmin.js'
|
||
import { sendStaffMail } from './mailer.js'
|
||
import { createPushTimeToken } from './pushTimeToken.js'
|
||
|
||
/**
|
||
* Push-Zeitmail (Vorlage T15): nach einem neuen Git-Push-Arbeitsblatt bekommt die pushende Person
|
||
* eine Mail mit Ticket- und Push-Infos und Schnell-Knoepfen zum Eintragen der Zeit (/zeit/<token>).
|
||
*/
|
||
|
||
const QUICK_MINUTES = [15, 30, 45, 60, 90, 120, 180]
|
||
const MAX_COMMITS = 10
|
||
const DESCRIPTION_MAX = 300
|
||
|
||
// Deutsche Bezeichnungen wie in WOMS (lib/ticketStatus.js)
|
||
const STATUS_LABELS = {
|
||
Open: 'Offen',
|
||
Assigned: 'Eingeplant',
|
||
Occupied: 'In Arbeit',
|
||
Awaiting: 'Wartet',
|
||
'In Test': 'Prüfung',
|
||
Closed: 'Erledigt',
|
||
Cancelled: 'Abgebrochen',
|
||
}
|
||
|
||
const norm = (value) => String(value || '').trim().toLowerCase()
|
||
|
||
/**
|
||
* Gitea-Pusher einem Mitarbeiter zuordnen - dieselbe Regel wie canEditWorksheetTimes in WOMS:
|
||
* Gitea-Name gegen Kuerzel oder Anzeigenamen, ohne Gross-/Kleinschreibung. Nur mit E-Mail-Adresse.
|
||
*/
|
||
export function findEmployeeForPusher(pusher, employees) {
|
||
const names = [pusher?.username, pusher?.login, pusher?.full_name].map(norm).filter(Boolean)
|
||
if (!names.length) return null
|
||
const sorted = [...(employees || [])].sort((a, b) => String(a.$createdAt || '').localeCompare(String(b.$createdAt || '')))
|
||
return (
|
||
sorted.find(
|
||
(emp) => String(emp.email || '').trim() && names.some((n) => n === norm(emp.shortcode) || n === norm(emp.displayName))
|
||
) || null
|
||
)
|
||
}
|
||
|
||
function commitLines(commits) {
|
||
const list = Array.isArray(commits) ? commits : []
|
||
const lines = list.slice(0, MAX_COMMITS).map((commit) => {
|
||
const sha = String(commit.id || commit.sha || '').slice(0, 7)
|
||
const title = String(commit.message || '').trim().split('\n')[0]
|
||
return `${sha} ${title}`.trim()
|
||
})
|
||
if (list.length > MAX_COMMITS) lines.push(`… und ${list.length - MAX_COMMITS} weitere`)
|
||
return lines.join('\n') || '(keine Commit-Details)'
|
||
}
|
||
|
||
function shorten(text, max) {
|
||
const value = String(text || '').trim()
|
||
return value.length > max ? `${value.slice(0, max)}…` : value
|
||
}
|
||
|
||
/** Werte fuer Vorlage T15 */
|
||
export function buildPushTimeMail({ employee, ticket, worksheet, repoFullName, branch, commits, pushedAt = new Date() }) {
|
||
const token = createPushTimeToken({ worksheetId: worksheet.$id, employeeId: employee.$id })
|
||
const base = `${config.publicBaseUrl}/zeit/${token}`
|
||
const { date, time } = berlinDateTime(pushedAt)
|
||
const woid = String(ticket?.woid || worksheet?.woid || '')
|
||
const links = Object.fromEntries(QUICK_MINUTES.map((m) => [`link_${m}`, `${base}?min=${m}`]))
|
||
|
||
return {
|
||
template: 'T15',
|
||
values: {
|
||
vorname: String(employee.displayName || '').trim().split(/\s+/)[0] || 'du',
|
||
woid,
|
||
kunde: ticket?.customerName || 'ohne Kunde',
|
||
ticket_titel: ticket?.topic || '',
|
||
ticket_beschreibung: shorten(ticket?.details, DESCRIPTION_MAX),
|
||
ticket_status: STATUS_LABELS[ticket?.status] || ticket?.status || '',
|
||
repo: repoFullName,
|
||
branch,
|
||
push_zeit: `${date} ${time.slice(0, 2)}:${time.slice(2)}`,
|
||
anzahl_commits: Array.isArray(commits) ? commits.length : 0,
|
||
commits: commitLines(commits),
|
||
...links,
|
||
link_andere: base,
|
||
ticket_link: `${config.womsBaseUrl}/tickets?woid=${encodeURIComponent(woid)}`,
|
||
},
|
||
}
|
||
}
|
||
|
||
/** Mail verschicken; wirft nie (Webhook darf daran nicht scheitern). */
|
||
export async function sendPushTimeMail({ ticket, worksheet, repoFullName, branch, commits, pusher, pushedAt }) {
|
||
try {
|
||
const employees = await listDocuments(config.collections.employees, [Query.limit(100)])
|
||
const employee = findEmployeeForPusher(pusher, employees)
|
||
if (!employee) {
|
||
const name = pusher?.username || pusher?.login || pusher?.full_name || '?'
|
||
console.warn(`[pushTimeMail] Pusher "${name}" keinem Mitarbeiter mit E-Mail zugeordnet – keine Zeitmail`)
|
||
return { sent: false, reason: 'no_employee' }
|
||
}
|
||
const mail = buildPushTimeMail({ employee, ticket, worksheet, repoFullName, branch, commits, pushedAt })
|
||
await sendStaffMail(employee.email, mail)
|
||
return { sent: true }
|
||
} catch (err) {
|
||
console.error('[pushTimeMail] Versand fehlgeschlagen:', err.message)
|
||
return { sent: false, reason: err.message }
|
||
}
|
||
}
|