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 * (wie "Zeit nachtragen" in WOMS). Ungueltiges Datum/Uhrzeit -> null. */ export function startFromEnd(endDate, endTime, minutes) { const date = String(endDate || '').match(/^(\d{2})\.(\d{2})\.(\d{4})$/) const time = String(endTime || '').match(/^(\d{2})(\d{2})$/) if (!date || !time) return null const [day, month, year] = [Number(date[1]), Number(date[2]), Number(date[3])] const [hours, mins] = [Number(time[1]), Number(time[2])] const end = new Date(Date.UTC(year, month - 1, day, hours, mins)) // 31.02. o. ae. rollt in Date.UTC weiter - dann ist das Datum ungueltig if (end.getUTCDate() !== day || end.getUTCMonth() !== month - 1 || hours > 23 || mins > 59) return null const start = new Date(end.getTime() - 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' | 'invalid', worksheet?: object }>} * invalid: Push-Datum/-Uhrzeit im Arbeitsblatt unbrauchbar (nichts gespeichert). * Andere Appwrite-Fehler als 404 werden weitergeworfen. */ export async function applyPushTime(worksheetId, minutes) { return withLocks([`ws-time:${worksheetId}`], async () => { let ws try { ws = await getDocument(config.collections.worksheets, worksheetId) } catch (err) { if (err?.status === 404) return { status: 'missing' } throw err } if (ws.serviceType !== 'GIT') return { status: 'not_git', worksheet: ws } if (!needsTimeEntry(ws)) return { status: 'already', worksheet: ws } const start = startFromEnd(ws.endDate, ws.endTime, minutes) if (!start) return { status: 'invalid', worksheet: ws } const { startDate, startTime } = start const worksheet = await updateDocument(config.collections.worksheets, worksheetId, { startDate, startTime, totalTime: minutes, isComment: false, }) return { status: 'saved', worksheet } }) }