92 lines
3.6 KiB
JavaScript
92 lines
3.6 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
|
|
* (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)
|
|
}
|
|
|
|
/** Zeiten nur in 15-Minuten-Schritten (wie WOMS lib/timeSteps.js) */
|
|
export const TIME_STEP = 15
|
|
|
|
/** 15-720 in 15er-Schritten 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 >= TIME_STEP && value <= MAX_MINUTES && value % TIME_STEP === 0 ? 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 }
|
|
})
|
|
}
|