AddOn/Datenexport_Zeiterfassung/test2.html hinzugefügt
This commit is contained in:
parent
5f32f4aa2d
commit
dee8f6ebf7
|
|
@ -0,0 +1,244 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>WebAPI - Test</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; margin: 20px; max-width: 600px; }
|
||||
label, select, input, button { display: block; width: 100%; margin-top: 10px; padding: 8px; }
|
||||
pre { background: #f0f0f0; padding: 10px; white-space: pre-wrap; max-height: 300px; overflow-y: auto; }
|
||||
#step2, #step3 { margin-top: 20px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>WebAPI - Test</h1>
|
||||
|
||||
<div id="step1">
|
||||
<label for="apiUrl">WebAPI URL (z.B. https://time.mycompany.de/zsvc):</label>
|
||||
<input type="text" id="apiUrl" placeholder="https://time.mycompany.de/zsvc" />
|
||||
|
||||
<label for="token">API Token:</label>
|
||||
<input type="text" id="token" placeholder="API Token hier eingeben" />
|
||||
|
||||
<button id="connectBtn">Verbinden und Daten laden</button>
|
||||
</div>
|
||||
|
||||
<div id="step2" style="display:none;">
|
||||
<label for="organizationUnit">Organisationseinheit:</label>
|
||||
<select id="organizationUnit"></select>
|
||||
|
||||
<label for="exportDefinition">Export-Definition:</label>
|
||||
<select id="exportDefinition"></select>
|
||||
|
||||
<label for="parserSelect">Parser auswählen (optional):</label>
|
||||
<select id="parserSelect">
|
||||
<option value="">-- Kein Parser --</option>
|
||||
<option value="persönliche_kalender_fehlzeiten_mit_tagen">persönliche_kalender_fehlzeiten_mit_tagen</option>
|
||||
<!-- Weitere Parser können hier hinzugefügt werden -->
|
||||
</select>
|
||||
|
||||
<label for="dateFrom">Von (dd.mm.yyyy):</label>
|
||||
<input type="date" id="dateFrom" />
|
||||
|
||||
<label for="dateUntil">Bis (dd.mm.yyyy):</label>
|
||||
<input type="date" id="dateUntil" />
|
||||
|
||||
<button id="requestExport">Export anfragen</button>
|
||||
</div>
|
||||
|
||||
<div id="step3" style="margin-top: 20px;">
|
||||
<h2>Export Daten</h2>
|
||||
<pre id="exportResult">Noch keine Daten</pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let baseUrl = '';
|
||||
let token = '';
|
||||
let apiSite = '';
|
||||
|
||||
async function apiRequest(baseUrl, token, apiSite, method, endpoint, body = null) {
|
||||
const url = baseUrl.replace(/\/+$/g, '') + (apiSite ? '/' + apiSite.replace(/^\/+|\/+$/g, '') : '') + '/' + endpoint.replace(/^\/+/, '');
|
||||
const headers = { 'Authorization': token };
|
||||
if (body) headers['Content-Type'] = 'application/json';
|
||||
const options = { method: method.toUpperCase(), headers };
|
||||
if (body) options.body = JSON.stringify(body);
|
||||
const response = await fetch(url, options);
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`API Fehler ${response.status}: ${errorText}`);
|
||||
}
|
||||
const contentType = response.headers.get('content-type') || '';
|
||||
return contentType.includes('application/json') ? response.json() : response.text();
|
||||
}
|
||||
|
||||
function parseCsvToFilteredArray(csvContent) {
|
||||
const feiertage = [
|
||||
'Neujahr', 'Karfreitag', 'Ostermontag', 'Tag der Arbeit',
|
||||
'Christi Himmelfahrt', 'Pfingstsonntag', 'Pfingstmontag',
|
||||
'Fronleichnam', 'Mariä Himmelfahrt', 'Tag der Deutschen Einheit',
|
||||
'Allerheiligen', '1. Weihnachtstag', '2. Weihnachtstag'
|
||||
];
|
||||
|
||||
const personen = {};
|
||||
const lines = csvContent.replace(/\r\n|\r/g, '\n').split('\n');
|
||||
|
||||
for (let line of lines) {
|
||||
line = line.trim();
|
||||
if (line === '') continue;
|
||||
|
||||
const fields = line.split(';');
|
||||
if (fields.length < 11) continue;
|
||||
|
||||
const [
|
||||
nr, nachname, vorname, datum, email,
|
||||
fehlzeitNR1HT, fehlzeitNR2HT,
|
||||
fehlzeitName1HT, fehlzeitName2HT,
|
||||
tagtypNR, tagtypName
|
||||
] = fields;
|
||||
|
||||
const hatFehlzeit = fehlzeitNR1HT !== '' || fehlzeitNR2HT !== '';
|
||||
const istFeiertag = feiertage.includes(tagtypName);
|
||||
|
||||
if (!hatFehlzeit && !istFeiertag) continue;
|
||||
|
||||
const personKey = `${nr}|${nachname}|${vorname}|${email}`;
|
||||
|
||||
if (!personen[personKey]) {
|
||||
personen[personKey] = {
|
||||
nr,
|
||||
nachname,
|
||||
vorname,
|
||||
email,
|
||||
tage_fehlzeit: [],
|
||||
tage_feiertage: []
|
||||
};
|
||||
}
|
||||
|
||||
const tagData = {
|
||||
datum,
|
||||
fehlzeitNR1HT,
|
||||
fehlzeitNR2HT,
|
||||
fehlzeitName1HT,
|
||||
fehlzeitName2HT,
|
||||
tagtypNR,
|
||||
tagtypName
|
||||
};
|
||||
|
||||
if (hatFehlzeit) personen[personKey].tage_fehlzeit.push(tagData);
|
||||
if (istFeiertag) personen[personKey].tage_feiertage.push(tagData);
|
||||
}
|
||||
|
||||
return Object.values(personen)
|
||||
.filter(p => p.tage_fehlzeit.length > 0 || p.tage_feiertage.length > 0)
|
||||
.sort((a, b) => {
|
||||
const keyA = `${a.nachname}|${a.vorname}`.toLowerCase();
|
||||
const keyB = `${b.nachname}|${b.vorname}`.toLowerCase();
|
||||
return keyA.localeCompare(keyB);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('connectBtn').addEventListener('click', async () => {
|
||||
baseUrl = document.getElementById('apiUrl').value.trim();
|
||||
token = document.getElementById('token').value.trim();
|
||||
|
||||
if (!baseUrl || !token) {
|
||||
alert('Bitte WebAPI URL und Token eingeben.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const orgUnits = await apiRequest(baseUrl, token, apiSite, 'GET', 'api/organization/');
|
||||
const exportDefs = await apiRequest(baseUrl, token, apiSite, 'GET', 'api/export/');
|
||||
|
||||
const orgSelect = document.getElementById('organizationUnit');
|
||||
orgSelect.innerHTML = '';
|
||||
orgUnits.forEach(org => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = org.ObjectId || '';
|
||||
opt.textContent = org.ObjectNaming || org.ObjectPatternNumber || org.ObjectShortTerm;
|
||||
orgSelect.appendChild(opt);
|
||||
});
|
||||
|
||||
const exportSelect = document.getElementById('exportDefinition');
|
||||
exportSelect.innerHTML = '';
|
||||
exportDefs.forEach(def => {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = def.ObjectId || '';
|
||||
opt.textContent = def.ObjectNaming || def.ObjectPatternNumber || def.ObjectShortTerm;
|
||||
exportSelect.appendChild(opt);
|
||||
});
|
||||
|
||||
document.getElementById('step1').style.display = 'none';
|
||||
document.getElementById('step2').style.display = 'block';
|
||||
|
||||
const today = new Date();
|
||||
const lastWeek = new Date(today);
|
||||
lastWeek.setDate(today.getDate() - 7);
|
||||
document.getElementById('dateFrom').value = lastWeek.toISOString().split('T')[0];
|
||||
document.getElementById('dateUntil').value = today.toISOString().split('T')[0];
|
||||
|
||||
} catch (e) {
|
||||
alert('Fehler beim Laden der Daten: ' + e.message);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('requestExport').addEventListener('click', async () => {
|
||||
const exportDefinitionId = document.getElementById('exportDefinition').value;
|
||||
const organizationUnitId = document.getElementById('organizationUnit').value;
|
||||
const dateFrom = document.getElementById('dateFrom').value;
|
||||
const dateUntil = document.getElementById('dateUntil').value;
|
||||
const parserType = document.getElementById('parserSelect').value;
|
||||
|
||||
if (!exportDefinitionId || !organizationUnitId || !dateFrom || !dateUntil) {
|
||||
alert('Bitte alle Felder ausfüllen.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const guid = await apiRequest(baseUrl, token, apiSite, 'POST', 'api/export', {
|
||||
ExportDefinition: exportDefinitionId,
|
||||
organizationUnit: organizationUnitId,
|
||||
DateFrom: dateFrom,
|
||||
DateUntil: dateUntil
|
||||
});
|
||||
|
||||
const pre = document.getElementById('exportResult');
|
||||
pre.textContent = 'Job gestartet (GUID: ' + guid + '), warte auf Ergebnis...';
|
||||
|
||||
const poll = async () => {
|
||||
try {
|
||||
const data = await apiRequest(baseUrl, token, apiSite, 'GET', `api/export/${guid}`);
|
||||
if (typeof data === 'string') {
|
||||
let output = data;
|
||||
if (parserType === 'persönliche_kalender_fehlzeiten_mit_tagen') {
|
||||
try {
|
||||
const parsed = parseCsvToFilteredArray(data);
|
||||
output = JSON.stringify(parsed, null, 2);
|
||||
} catch (err) {
|
||||
output = 'Fehler beim Parsen:\n' + err.message + '\n\nOriginaldaten:\n' + data;
|
||||
}
|
||||
}
|
||||
pre.textContent = output;
|
||||
} else {
|
||||
pre.textContent = JSON.stringify(data, null, 2);
|
||||
if (data.Result === 'JobPending') {
|
||||
pre.textContent += '\nNoch in Bearbeitung... erneut versuchen in 60 Sek.';
|
||||
setTimeout(poll, 60000);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Polling-Fehler:', err);
|
||||
}
|
||||
};
|
||||
|
||||
setTimeout(poll, 5000);
|
||||
|
||||
} catch (e) {
|
||||
alert('Fehler beim Export: ' + e.message);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue