// RMLWorkorderAdmin.js Vue.component('r-m-l-workorder-admin', { template: `
{{ workordersToAssign.length }} Workorder(s) zuweisen:
`, data() { return { window, workordersToAssign: [], editingWorkorderId: null, editingDeadlineId: null, companies: [], massAssignCompanyId: null, massAssignLoading: false, crudConfig: { ...window.TT_CONFIG.CRUD_CONFIG, selectable: false, expandable: true, customRowClass: (row) => { const deadlineDate = moment.unix(row.deadlineDate); if (['completed', 'new'].includes(row.status) || !deadlineDate.isValid()) { return 'tt-rml-workorder-irrelevant'; } if (['correction_requested', 'intervention_required'].includes(row.status)) { return 'tt-rml-workorder-high'; } const daysLeft = deadlineDate.diff(moment(), 'days'); if (daysLeft <= 7) return 'tt-rml-workorder-urgent'; if (daysLeft <= 21) return 'tt-rml-workorder-medium'; return 'tt-rml-workorder-ontrack'; }, additionalActions: [] } } }, async mounted() { const response = await axios.get(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/getCompanies`); this.companies = response.data; }, methods: { addToAssignList(row) { if (!this.workordersToAssign.includes(row.id)) { this.workordersToAssign.push(row.id); } }, removeFromAssignList(row) { this.workordersToAssign = this.workordersToAssign.filter(id => id !== row.id); }, getStatusColumn(status) { const column = this.crudConfig.columns.find(c => c.key === 'status'); return column.table.filterOptions.find(opt => opt.value === status) || {}; }, formatDate(timestamp) { if (!timestamp) return '–'; return window.moment.unix(timestamp).format('DD.MM.YYYY'); }, async assignCompany(workorder, companyId) { if (!companyId) { this.editingWorkorderId = null; return; } const payload = { workorderId: workorder.id, companyId: companyId }; try { const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/assignWorkorder`, payload); if (response.data.success) { window.notify('success', response.data.message); this.$refs.table.$refs.table.refreshTable(); } else { window.notify('error', response.data.message || 'Ein Fehler ist aufgetreten.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.editingWorkorderId = null; } }, async massAssignCompanies(companyId) { if (!companyId) return; if (!confirm(`${this.workordersToAssign.length} Workorder(s) der ausgewählten Firma zuweisen?`)) { this.massAssignCompanyId = null; // Reset select on cancel return; } this.massAssignLoading = true; const payload = { companyId: companyId, workorderIds: this.workordersToAssign }; try { const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/massAssignWorkorders`, payload); if (response.data.success) { window.notify('success', response.data.message); this.workordersToAssign = []; this.$refs.table.$refs.table.refreshTable(); } else { window.notify('error', response.data.message || 'Ein Fehler ist aufgetreten.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.massAssignLoading = false; this.massAssignCompanyId = null; } }, async updateDeadline(workorder, newDate) { if (!newDate) { this.editingDeadlineId = null; return; } try { const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/updateDeadline`, { workorderId: workorder.id, deadlineDate: newDate }); if (response.data.success) { window.notify('success', response.data.message); this.$refs.table.$refs.table.refreshTable(); } else { window.notify('error', response.data.message || 'Ein Fehler ist aufgetreten.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.editingDeadlineId = null; } }, async acceptDocumentation(workorderId) { if (!confirm('Soll die Dokumentation für diesen Arbeitsauftrag wirklich akzeptiert und der Auftrag abgeschlossen werden?')) return; try { const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/acceptDocumentation`, { workorderId }); if (response.data.success) { window.notify('success', response.data.message); this.$refs.table.$refs.table.refreshTable(); } else { window.notify('error', response.data.message || 'Ein Fehler ist aufgetreten.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } }, async setToProblemSolved(row) { const text = prompt('Bitte geben Sie einen kurzen Text für den Journaleintrag ein:', ''); if (text === null) return; // User cancelled if (!text.trim()) { window.notify('error', 'Bitte geben Sie einen Text ein.'); return; } try { const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/setToProblemSolved`, { workorderId: row.id, text: text }); if (response.data.success) { window.notify('success', response.data.message); this.$refs.table.$refs.table.refreshTable(); } else { window.notify('error', response.data.message || 'Ein Fehler ist aufgetreten.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } } } }); Vue.component('traffic-light', { props: ['deadline', 'status'], computed: { lightInfo() { if (['completed', 'new'].includes(this.status)) return {color: '#cccccc', title: 'Status irrelevant für Dringlichkeit'}; const now = moment(); const deadlineDate = moment.unix(this.deadline); if (!deadlineDate.isValid()) return {color: '#cccccc', title: 'Keine Deadline gesetzt'}; if (deadlineDate.isBefore(now)) return {color: '#dc3545', title: 'Deadline überschritten'}; const daysLeft = deadlineDate.diff(now, 'days'); if (daysLeft <= 7) return {color: '#dc3545', title: 'Dringend: Weniger als 1 Woche'}; if (daysLeft <= 21) return {color: '#ffc107', title: 'Mittel: Weniger als 3 Wochen'}; return {color: '#28a745', title: 'Im Plan: Mehr als 3 Wochen'}; } }, template: `●` }); Vue.component('rml-documentation-viewer-admin', { props: ['workorderId'], template: `
Korrektur anfordern

Wählen Sie die zu korrigierenden Dokumente aus der Galerie aus und geben Sie einen Grund an.

Dokumentation akzeptieren

Prüfen Sie, ob alle erforderlichen Dokumente vorhanden und korrekt sind.

  • {{ docType.text }}

Journal
  • {{ formatDate(log.create) }} ({{ log.createByName }}):
    {{ log.text }}
Keine Journaleinträge.
`, data() { return { loading: true, correctionLoading: false, docs: [], journals: [], selectedDocs: [], correctionText: '', newJournalMessage: '', addingJournalEntry: false, requiredDocTypes: [ { value: 'photo_hup_mounted', text: 'Foto vom montierten HÜP' }, { value: 'photo_hup_open', text: 'Foto von dem offenen HÜP' }, { value: 'photo_splice_cassette_hup', text: 'Foto der Spleißkassette – HÜP' }, { value: 'photo_splice_cassette_fcp', text: 'Foto der Spleißkassette - FCP' }, { value: 'photo_hup_closed_stickers', text: 'Foto vom geschlossenen HÜP mit allen Aufklebern' }, { value: 'photo_fcp_labeled', text: 'Foto vom FCP beschriftet' }, { value: 'photo_patch_position_osp', text: 'Foto der Patch-Position - OSP-Seite' }, { value: 'photo_patch_position_anb', text: 'Foto der Patch-Position - ANB-Seite' }, { value: 'measurement_protocol_otdr', text: 'ODTR – Messung (1310nm & 1550nm)' }, ] } }, methods: { isUploaded(docType) { return this.docs.some(doc => doc.documentType === docType); }, async fetchData() { this.loading = true; try { const response = await axios.get(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/getDocumentation`, { params: { workorderId: this.workorderId }}); this.docs = response.data.docs; this.journals = response.data.journals; } catch(e) { window.notify('error', 'Dokumentation konnte nicht geladen werden.'); } finally { this.loading = false; } }, async requestCorrection() { if (!this.correctionText) return window.notify('error', 'Bitte geben Sie einen Grund für die Korrektur an.'); if (this.selectedDocs.length === 0) return window.notify('error', 'Bitte wählen Sie mindestens ein Dokument für die Korrektur aus.'); this.correctionLoading = true; try { const payload = { workorderId: this.workorderId, text: this.correctionText, fileIds: this.selectedDocs }; const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/requestCorrection`, payload); if (response.data.success) { window.notify('success', response.data.message); this.correctionText = ''; this.selectedDocs = []; await this.fetchData(); this.$emit('workorder-updated'); } else { window.notify('error', response.data.message); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } this.correctionLoading = false; }, async addJournalEntry() { if (!this.newJournalMessage.trim()) { return window.notify('error', 'Bitte geben Sie eine Nachricht ein.'); } this.addingJournalEntry = true; try { const response = await axios.post(`${window.TT_CONFIG.BASE_PATH}/RMLWorkorderAdmin/addJournal`, { workorderId: this.workorderId, text: this.newJournalMessage }); if (response.data.success) { window.notify('success', response.data.message || 'Journal-Eintrag hinzugefügt.'); this.newJournalMessage = ''; this.journals = response.data.journals; } else { window.notify('error', response.data.message || 'Eintrag konnte nicht gespeichert werden.'); } } catch (e) { window.notify('error', 'Ein Netzwerkfehler ist aufgetreten.'); } finally { this.addingJournalEntry = false; } }, formatDate(timestamp) { return window.moment.unix(timestamp).format('DD.MM.YYYY HH:mm'); }, }, mounted() { this.fetchData(); } });