rmlworkorder major upgrade

This commit is contained in:
Luca Haid
2025-09-02 08:36:33 +00:00
parent 549027a67c
commit b173a6edc1
24 changed files with 1762 additions and 2073 deletions

View File

@@ -0,0 +1,139 @@
<?php
// WorkorderBaseController.php
class WorkorderBaseController extends TTCrud
{
/**
* @var array Shared status column definition for consistency.
*/
protected array $statusColumn = [
'key' => 'status', 'text' => 'Status', 'modal' => false, 'table' => ['filter' => 'iconSelect', 'filterOptions' => [
['value' => 'new', 'text' => 'Neu', 'icon' => 'fas fa-star text-primary'],
['value' => 'assigned', 'text' => 'Zugewiesen', 'icon' => 'fas fa-user-check text-info'],
['value' => 'scheduled', 'text' => 'Geplant', 'icon' => 'fas fa-calendar-check text-warning'],
['value' => 'correction_requested', 'text' => 'Korrektur angefordert', 'icon' => 'fas fa-exclamation-triangle text-danger'],
['value' => 'intervention_required', 'text' => 'Eingriff erforderlich', 'icon' => 'fas fa-times-circle text-danger'],
['value' => 'civil_engineering_required', 'text' => 'Tiefbau benötigt', 'icon' => 'fas fa-hard-hat text-orange'],
['value' => 'civil_engineering_completed', 'text' => 'Tiefbau abgeschlossen', 'icon' => 'fas fa-hard-hat text-success'],
['value' => 'problem_solved', 'text' => 'Problem gelöst', 'icon' => 'fas fa-check-circle text-success'],
['value' => 'documented', 'text' => 'Dokumentiert', 'icon' => 'fas fa-file-alt text-success'],
['value' => 'completed', 'text' => 'Abgeschlossen', 'icon' => 'fas fa-check-double text-secondary'],
['value' => 'cancelled', 'text' => 'Abgebrochen', 'icon' => 'fas fa-ban text-danger'],
]]
];
protected array $additionalJS = ["js/pages/WorkorderBase/WorkorderBase.js"];
protected array $additionalHead = ["<link rel='stylesheet' href='/js/pages/WorkorderBase/WorkorderBase.css'>"];
/**
* Gets the display text for a given status key.
* @param string $statusKey
* @return string
*/
protected function getStatusText(string $statusKey): string
{
$statusMap = array_column($this->statusColumn['table']['filterOptions'] ?? [], 'text', 'value');
return $statusMap[$statusKey] ?? ucfirst(str_replace('_', ' ', $statusKey));
}
//region SHARED ACTIONS
/**
* Fetches documentation and journal entries for a given workorder.
*/
protected function getDocumentationAction()
{
if (empty($this->request->workorderId)) self::sendError("Arbeitsauftrags-ID fehlt.");
$docs = WorkorderDocumentationModel::getAll(['workorderId' => $this->request->workorderId], null, 0, ['key' => 'create', 'order' => 'ASC']);
$journals = WorkorderJournalModel::getAll(['workorderId' => $this->request->workorderId], null, 0, ['key' => 'create', 'order' => 'DESC']);
$tenantConfig = $this->getTenantConfigFromWorkorder((int)$this->request->workorderId);
if ($tenantConfig && !empty($tenantConfig->documentationTypes)) {
$customTypes = json_decode($tenantConfig->documentationTypes, true);
$customMap = array_column($customTypes, 'text', 'value');
$translationMap = array_merge(['civil_engineering_photo' => 'Tiefbau_Foto'], $customMap);
}
$responseDocs = [];
$typeCounts = [];
foreach ($docs as $doc) {
$file = new File($doc->fileId);
$documentTypeKey = $doc->documentType;
$typeCounts[$documentTypeKey] = ($typeCounts[$documentTypeKey] ?? 0) + 1;
$originalFilename = $file->orig_filename ?? $file->filename;
$extension = pathinfo($originalFilename, PATHINFO_EXTENSION);
$translatedType = $translationMap[$documentTypeKey] ?? $documentTypeKey;
$newFilename = "{$translatedType}_{$typeCounts[$documentTypeKey]}." . strtolower($extension);
$responseDocs[] = [
'id' => $doc->id, 'fileId' => $doc->fileId, 'fileName' => $newFilename, 'description' => $doc->description,
'documentType' => $documentTypeKey, 'userName' => UserModel::getOne($doc->createBy)->name ?? 'Unbekannt',
'mimetype' => $file->mimetype ?? 'application/octet-stream', 'create' => $doc->create
];
}
foreach ($journals as $journal) {
$journal->createByName = UserModel::getOne($journal->createBy)->name ?? 'Unbekannt';
}
self::returnJson(['docs' => $responseDocs, 'journals' => $journals]);
}
/**
* Adds a new entry to a workorder's journal.
*/
protected function addJournalAction()
{
$post = json_decode(file_get_contents('php://input'), true);
if (empty($post['workorderId']) || empty(trim($post['text']))) self::sendError("Arbeitsauftrags-ID und Text sind erforderlich.");
WorkorderJournalModel::create(['workorderId' => $post['workorderId'], 'text' => $post['text'], 'createBy' => $this->user->id, 'create' => time()]);
$journals = WorkorderJournalModel::getAll(['workorderId' => $post['workorderId']], null, 0, ['key' => 'create', 'order' => 'DESC']);
foreach ($journals as $journal) {
$journal->createByName = UserModel::getOne($journal->createBy)->name ?? 'Unbekannt';
}
self::returnJson(['success' => true, 'message' => 'Journaleintrag hinzugefügt.', 'journals' => $journals]);
}
/**
* Updates the additional info field for a workorder.
*/
protected function updateAdditionalInfoAction()
{
$post = json_decode(file_get_contents('php://input'), true);
if (empty($post['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderModel::get($post['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$oldInfo = $workorder->additionalInfo;
$newInfo = $post['additionalInfo'] ?? null;
$workorder->additionalInfo = $newInfo;
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id, 'text' => "Zusatzinfo geändert.\nAlt: '{$oldInfo}'\nNeu: '{$newInfo}'",
'create' => time(), 'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Zusatzinfo aktualisiert.', 'newInfo' => $newInfo]);
}
//endregion
protected function getTenantConfigFromWorkorder(int $workorderId) {
if (empty($workorderId)) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderModel::get($workorderId);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$preorder = new Preorder($workorder->preorderId);
if (!$preorder->id) self::sendError("Vorbestellung nicht gefunden.");
$campaign = new Preordercampaign($preorder->preordercampaign_id);
if (!$campaign->id) self::sendError("Kampagne nicht gefunden.");
$network = NetworkModel::getOne($campaign->network_id);
if (!$network) self::sendError("Netzwerk nicht gefunden.");
return WorkorderTenantConfigModel::getFirst(['addressId' => $network->owner_id]) ?? null;
}
}