diff --git a/application/RimoWorkorder/RimoWorkorder.php b/application/RimoWorkorder/RimoWorkorder.php index e08448269..0b6bccc89 100644 --- a/application/RimoWorkorder/RimoWorkorder.php +++ b/application/RimoWorkorder/RimoWorkorder.php @@ -79,7 +79,7 @@ class RimoWorkorder extends mfBaseModel { $fn = 'aha_lageplan_' . $this->id . '_' . time() . '.png'; $file = FileModel::create(['name' => 'AHA Lageplan ' . $this->rimo_name, 'filename' => $fn, 'store_filename' => $fn, 'orig_filename' => 'AHA_Lageplan_' . $this->rimo_name . '.png', - 'mimetype' => 'image/png', 'subfolder' => 'aha_maps']); + 'mimetype' => 'image/png', 'subfolder' => 'aha_maps', 'create_by' => 1]); if ($file->save()) { $dir = MFUPLOAD_FILE_SAVE_PATH . '/aha_maps'; if (!is_dir($dir)) mkdir($dir, 0755, true); diff --git a/public/js/pages/WorkorderAdmin/WorkorderAdmin.js b/public/js/pages/WorkorderAdmin/WorkorderAdmin.js index 561f6f1ab..0cf9a40d4 100644 --- a/public/js/pages/WorkorderAdmin/WorkorderAdmin.js +++ b/public/js/pages/WorkorderAdmin/WorkorderAdmin.js @@ -90,8 +90,8 @@ Vue.component('workorder-admin', { diff --git a/public/js/pages/WorkorderBase/WorkorderBase.js b/public/js/pages/WorkorderBase/WorkorderBase.js index 9a4f914c5..758b31278 100644 --- a/public/js/pages/WorkorderBase/WorkorderBase.js +++ b/public/js/pages/WorkorderBase/WorkorderBase.js @@ -27,25 +27,56 @@ Vue.component('civil-engineering-manager', {
-
+
-
Tiefbau-Arbeiten
+
Tiefbau-Arbeiten

Schließen Sie den Tiefbau-Auftrag ab. Laden Sie Dokumente hoch, falls erforderlich.

+ +
+
Checkliste
+
    +
  • + + {{ docType.text }} +
  • +
+
+
- - Bitte laden Sie mindestens ein Dokument hoch, um den Auftrag abzuschließen. + + Bitte laden Sie mindestens ein Tiefbau-Dokument hoch, um den Auftrag abzuschließen.
+ +
+
Journal
+
+
    +
  • + {{ formatDate(log.create) }} ({{ log.createByName }}): +
    {{ log.text }}
    +
  • +
+
Keine Journaleinträge.
+
+ +
+
-
+
Dokument hochladen
+
@@ -56,14 +87,21 @@ Vue.component('civil-engineering-manager', {
+ + @delete-file="deleteDocumentation" + @update-file="updateDocumentation"> + -
Für diesen Auftraggeber ist keine Dokumentation für Tiefbau-Arbeiten erforderlich.
+ +
+ Für diesen Auftraggeber ist keine Dokumentation für Tiefbau-Arbeiten erforderlich. +
@@ -72,25 +110,43 @@ Vue.component('civil-engineering-manager', {
`, data: () => ({ - loading: true, uploading: false, completing: false, docsRequired: false, - uploadedFiles: [], uploadData: { files: [], description: '' }, showCompleteModal: false + loading: true, uploading: false, completing: false, + docsRequired: false, tiefbauSeesNormalDocs: false, documentationTypes: [], + uploadedFiles: [], journals: [], + uploadData: { files: [], description: '', documentType: 'civil_engineering_photo' }, + showCompleteModal: false, + newJournalMessage: '', addingJournalEntry: false }), computed: { canComplete() { + if (this.tiefbauSeesNormalDocs) { + // When tiefbauSeesNormalDocs is enabled, can always complete (no strict requirements) + return true; + } + // Original logic: require at least one civil engineering doc if docsRequired return !this.docsRequired || this.uploadedFiles.length > 0; + }, + allDocTypes() { + return [...this.documentationTypes, { value: 'civil_engineering_photo', text: 'Tiefbau Foto' }, { value: 'other', text: 'Sonstiges' }]; } }, methods: { + formatDate(timestamp) { return timestamp ? window.moment.unix(timestamp).format('DD.MM.YYYY HH:mm') : '–'; }, + isUploaded(docType) { + return Array.isArray(this.uploadedFiles) && this.uploadedFiles.some(doc => doc.documentType === docType); + }, async fetchInitialData() { this.loading = true; try { const configRes = await axios.get(`${window.TT_CONFIG.BASE_PATH}/WorkorderCompany/getTenantConfig`, { params: { workorderId: this.workorderId } }); this.docsRequired = configRes.data.civilEngineeringDocsRequired || false; + this.tiefbauSeesNormalDocs = configRes.data.tiefbauSeesNormalDocs || false; + this.documentationTypes = configRes.data.documentationTypes || []; - if(this.docsRequired) { - const docRes = await axios.get(`${window.TT_CONFIG.BASE_PATH}/${this.isAdmin ? 'WorkorderAdmin' : 'WorkorderCompany'}/getDocumentation`, { params: { workorderId: this.workorderId } }); - this.uploadedFiles = docRes.data.docs || []; - } + // Always load docs and journals + const docRes = await axios.get(`${window.TT_CONFIG.BASE_PATH}/${this.isAdmin ? 'WorkorderAdmin' : 'WorkorderCompany'}/getDocumentation`, { params: { workorderId: this.workorderId } }); + this.uploadedFiles = docRes.data.docs || []; + this.journals = docRes.data.journals || []; } catch (e) { window.notify('error', 'Konfiguration konnte nicht geladen werden.'); console.error(e); @@ -104,7 +160,7 @@ Vue.component('civil-engineering-manager', { this.uploading = true; const formData = new FormData(); formData.append('workorderId', this.workorderId); - formData.append('documentType', 'civil_engineering_photo'); + formData.append('documentType', this.uploadData.documentType || 'civil_engineering_photo'); formData.append('description', this.uploadData.description); for (const file of this.uploadData.files) formData.append('files[]', file); try { @@ -112,7 +168,7 @@ Vue.component('civil-engineering-manager', { if (data.success) { window.notify('success', data.message); this.$refs.fileInput.value = ''; - this.uploadData = { files: [], description: '' }; + this.uploadData = { files: [], description: '', documentType: this.tiefbauSeesNormalDocs ? this.documentationTypes[0]?.value : 'civil_engineering_photo' }; await this.fetchInitialData(); } else window.notify('error', data.error || 'Upload fehlgeschlagen.'); } catch (e) { @@ -131,6 +187,29 @@ Vue.component('civil-engineering-manager', { window.notify('error', 'Netzwerkfehler beim Löschen.'); } }, + async updateDocumentation(file) { + try { + const {data} = await axios.post(`${window.TT_CONFIG.BASE_PATH}/WorkorderCompany/updateDocumentation`, { id: file.id, documentType: file.documentType }); + if (data.success) { + window.notify('success', data.message); + await this.fetchInitialData(); + } else window.notify('error', data.message || 'Update fehlgeschlagen.'); + } catch (e) { + window.notify('error', 'Netzwerkfehler beim Update.'); + } + }, + async addJournalEntry() { + if (!this.newJournalMessage.trim()) return; + this.addingJournalEntry = true; + try { + const {data} = await axios.post(`${window.TT_CONFIG.BASE_PATH}/${this.isAdmin ? 'WorkorderAdmin' : 'WorkorderCompany'}/addJournal`, { workorderId: this.workorderId, text: this.newJournalMessage }); + if (data.success) { + this.newJournalMessage = ''; + this.journals = data.journals || []; + } else window.notify('error', data.message); + } catch (e) { window.notify('error', 'Netzwerkfehler'); } + finally { this.addingJournalEntry = false; } + }, async completeTask() { this.completing = true; try {