Files
Webklar-Kundenbereich/server/services/pushTimeEntry.js
T
2026-09-30 13:34:17 +00:00

76 lines
2.8 KiB
JavaScript

import { config } from '../config.js'
import { withLocks } from './keyedLock.js'
import { getDocument, updateDocument } from './appwriteAdmin.js'
/**
* Zeit fuer ein Git-Push-Arbeitsblatt eintragen (Push-Zeitmail). Ergebnis wie "Zeit nachtragen" in
* WOMS: Startzeit = Push-Zeit (Endzeit) minus Dauer, totalTime = Minuten, isComment = false.
* Eine schon eingetragene Zeit wird nie ueberschrieben - Aendern geht nur in WOMS.
*/
export const MAX_MINUTES = 720
const pad = (n) => String(n).padStart(2, '0')
/** Wand-Uhrzeit rueckwaerts rechnen ('tt.mm.jjjj', 'hhmm'); reine Kalenderrechnung, ohne Zeitzone. */
export function startFromEnd(endDate, endTime, minutes) {
const [day, month, year] = String(endDate).split('.').map(Number)
const hours = Number(String(endTime).slice(0, 2))
const mins = Number(String(endTime).slice(2, 4))
const start = new Date(Date.UTC(year, month - 1, day, hours, mins) - minutes * 60 * 1000)
return {
startDate: `${pad(start.getUTCDate())}.${pad(start.getUTCMonth() + 1)}.${start.getUTCFullYear()}`,
startTime: `${pad(start.getUTCHours())}${pad(start.getUTCMinutes())}`,
}
}
/** Git-Push ohne eingetragene Zeit (wie needsTimeEntry in WOMS) */
export function needsTimeEntry(ws) {
return ws?.serviceType === 'GIT' && !(ws.startTime && Number(ws.totalTime) > 0)
}
/** Ganze Minuten 1-720 aus Formular/Query, sonst null */
export function parseMinutes(raw) {
if (raw === null || raw === undefined) return null
const text = String(raw).trim()
if (!/^\d+$/.test(text)) return null
const value = Number(text)
return value >= 1 && value <= MAX_MINUTES ? value : null
}
/** 15 -> '15 Min', 60 -> '1 Std', 90 -> '1,5 Std', 130 -> '2 Std 10 Min' */
export function formatMinutes(min) {
const total = Number(min) || 0
if (total < 60) return `${total} Min`
const hours = Math.floor(total / 60)
const rest = total % 60
if (rest === 0) return `${hours} Std`
if (rest === 30) return `${hours},5 Std`
return `${hours} Std ${rest} Min`
}
/**
* @returns {Promise<{ status: 'saved' | 'already' | 'missing' | 'not_git', worksheet?: object }>}
*/
export async function applyPushTime(worksheetId, minutes) {
return withLocks([`ws-time:${worksheetId}`], async () => {
let ws
try {
ws = await getDocument(config.collections.worksheets, worksheetId)
} catch {
return { status: 'missing' }
}
if (ws.serviceType !== 'GIT') return { status: 'not_git', worksheet: ws }
if (!needsTimeEntry(ws)) return { status: 'already', worksheet: ws }
const { startDate, startTime } = startFromEnd(ws.endDate, ws.endTime, minutes)
const worksheet = await updateDocument(config.collections.worksheets, worksheetId, {
startDate,
startTime,
totalTime: minutes,
isComment: false,
})
return { status: 'saved', worksheet }
})
}