Files
thetool/application/WorkorderMphBase/WorkorderMphBaseController.php
2025-11-16 19:19:17 +01:00

305 lines
13 KiB
PHP

<?php
class WorkorderMphBaseController extends TTCrud
{
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' => 'in_progress', 'text' => 'In Bearbeitung', 'icon' => 'fas fa-cog text-warning'],
['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'],
['value' => 'archived', 'text' => 'Archiviert', 'icon' => 'fas fa-archive text-muted'],
]]
];
protected array $additionalJS = ["js/pages/WorkorderMphBase/WorkorderMphBase.js"];
protected array $additionalHead = ["<link rel='stylesheet' href='/js/pages/WorkorderMphBase/WorkorderMphBase.css'>"];
// Wohneinheit status options
protected array $wohneinheitStatuses = [
['value' => 1, 'text' => '10 - new'],
['value' => 12, 'text' => '241 - BEP installed (MD)'],
['value' => 13, 'text' => '242 - Inhouse cabling finished'],
['value' => 18, 'text' => '243 - Cable in stairwell'],
['value' => 14, 'text' => '244 - BEP installed (SD)'],
['value' => 15, 'text' => '245 - Installation Approved'],
['value' => 16, 'text' => '300 - ONT installed'],
];
protected function getStatusText(string $statusKey): string
{
$statusMap = array_column($this->statusColumn['table']['filterOptions'] ?? [], 'text', 'value');
return $statusMap[$statusKey] ?? ucfirst(str_replace('_', ' ', $statusKey));
}
protected function getWohneinheitStatusText(int $statusValue): string
{
$statusMap = array_column($this->wohneinheitStatuses, 'text', 'value');
return $statusMap[$statusValue] ?? "Status $statusValue";
}
//region SHARED ACTIONS
/**
* Fetches documentation and journal entries for a given workorder.
*/
protected function getDocumentationAction()
{
if (empty($this->request->workorderMphId)) self::sendError("Arbeitsauftrags-ID fehlt.");
$docs = WorkorderMphDocumentationModel::getAll(['workorderMphId' => intval($this->request->workorderMphId)], null, 0, ['key' => 'create', 'order' => 'ASC']);
$journals = WorkorderMphJournalModel::getAll(['workorderMphId' => intval($this->request->workorderMphId)], null, 0, ['key' => 'create', 'order' => 'DESC']);
$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);
$newFilename = "{$documentTypeKey}_{$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['workorderMphId']) || empty(trim($post['text']))) self::sendError("Arbeitsauftrags-ID und Text sind erforderlich.");
WorkorderMphJournalModel::create([
'workorderMphId' => $post['workorderMphId'],
'text' => $post['text'],
'createBy' => $this->user->id,
'create' => time()
]);
$journals = WorkorderMphJournalModel::getAll(['workorderMphId' => intval($post['workorderMphId'])], 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['workorderMphId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderMphModel::get($post['workorderMphId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$oldInfo = $workorder->additionalInfo;
$newInfo = $post['additionalInfo'] ?? null;
$workorder->additionalInfo = $newInfo;
WorkorderMphModel::update((array)$workorder);
WorkorderMphJournalModel::create([
'workorderMphId' => $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]);
}
/**
* Get all Wohneinheiten for a specific workorder with their statuses and notes
*/
protected function getWohneinheitenAction()
{
if (empty($this->request->workorderMphId)) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorderMphId = intval($this->request->workorderMphId);
$workorder = WorkorderMphModel::get($workorderMphId);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
// Get all Wohneinheiten for this Hausnummer from addressdb
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$hausnummerId = $db->escape($workorder->hausnummerId);
$sql = "SELECT w.id, w.bezeichner, w.contact
FROM Wohneinheit w
WHERE w.hausnummer_id = $hausnummerId
ORDER BY w.bezeichner";
$result = $db->query($sql);
$wohneinheiten = $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
// Get existing WorkorderMphWohneinheit records
$existingRecords = WorkorderMphWohneinheitModel::getAll(['workorderMphId' => $workorderMphId]);
$recordsMap = [];
foreach ($existingRecords as $record) {
$recordsMap[$record->wohneinheitId] = $record;
}
// Merge data
$response = [];
foreach ($wohneinheiten as $we) {
$record = $recordsMap[$we['id']] ?? null;
$response[] = [
'wohneinheitId' => intval($we['id']),
'bezeichner' => $we['bezeichner'],
'contact' => $we['contact'],
'status' => $record ? $record->status : 1,
'note' => $record ? $record->note : null,
'recordId' => $record ? $record->id : null,
];
}
self::returnJson(['wohneinheiten' => $response, 'statusOptions' => $this->wohneinheitStatuses]);
}
/**
* Update status and note for a specific Wohneinheit
*/
protected function updateWohneinheitAction()
{
$post = json_decode(file_get_contents('php://input'), true);
if (empty($post['workorderMphId']) || empty($post['wohneinheitId'])) {
self::sendError("Arbeitsauftrags-ID und Wohneinheit-ID sind erforderlich.");
}
$workorderMphId = intval($post['workorderMphId']);
$wohneinheitId = intval($post['wohneinheitId']);
$status = intval($post['status'] ?? 1);
$note = $post['note'] ?? null;
// Check if record exists
$existing = WorkorderMphWohneinheitModel::getFirst([
'workorderMphId' => $workorderMphId,
'wohneinheitId' => $wohneinheitId
]);
$oldStatus = $existing ? $existing->status : 1;
$oldNote = $existing ? $existing->note : null;
if ($existing) {
$existing->status = $status;
$existing->note = $note;
$existing->edit = time();
$existing->editBy = $this->user->id;
WorkorderMphWohneinheitModel::update((array)$existing);
} else {
WorkorderMphWohneinheitModel::create([
'workorderMphId' => $workorderMphId,
'wohneinheitId' => $wohneinheitId,
'status' => $status,
'note' => $note,
'create' => time(),
'createBy' => $this->user->id
]);
}
// Add journal entry if status or note changed
if ($oldStatus !== $status || $oldNote !== $note) {
$changes = [];
if ($oldStatus !== $status) {
$changes[] = "Status: " . $this->getWohneinheitStatusText($oldStatus) . "" . $this->getWohneinheitStatusText($status);
}
if ($oldNote !== $note) {
$changes[] = "Notiz aktualisiert";
}
WorkorderMphJournalModel::create([
'workorderMphId' => $workorderMphId,
'text' => "Wohneinheit $wohneinheitId: " . implode(', ', $changes),
'create' => time(),
'createBy' => $this->user->id,
]);
// If status is 241 (BEP MD) or 300 (ONT installed), set statusflag 200 on Wohneinheit
if (in_array($status, [12, 16])) { // 12=241 BEP MD, 16=300 ONT
$this->setWohneinheitStatusflag($wohneinheitId, 200);
}
}
self::returnJson(['success' => true, 'message' => 'Wohneinheit aktualisiert.']);
}
/**
* Set statusflag on Wohneinheit in addressdb
*/
private function setWohneinheitStatusflag(int $wohneinheitId, int $statusflagId)
{
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$weId = $db->escape($wohneinheitId);
$sfId = $db->escape($statusflagId);
// Check if statusflag already exists
$checkSql = "SELECT COUNT(*) as count FROM WohneinheitStatusflagValue WHERE wohneinheit_id = $weId AND statusflag_id = $sfId";
$result = $db->query($checkSql);
$exists = $result->fetch_assoc()['count'] > 0;
if (!$exists) {
$insertSql = "INSERT INTO WohneinheitStatusflagValue (wohneinheit_id, statusflag_id, create, createBy)
VALUES ($weId, $sfId, " . time() . ", " . $this->user->id . ")";
$db->query($insertSql);
}
}
/**
* Update checkbox documentation fields
*/
protected function updateCheckboxesAction()
{
$post = json_decode(file_get_contents('php://input'), true);
if (empty($post['workorderMphId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderMphModel::get($post['workorderMphId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$changes = [];
$checkboxFields = ['easement', 'btb', 'fttxLocationSupplied', 'conduitToHuepLaid', 'huepMounted', 'dropCableAvailable'];
foreach ($checkboxFields as $field) {
if (array_key_exists($field, $post)) {
$oldValue = $workorder->$field;
$newValue = $post[$field] ? 1 : 0;
if ($oldValue !== $newValue) {
$workorder->$field = $newValue;
$changes[] = "$field: " . ($newValue ? 'ja' : 'nein');
}
}
}
if (!empty($changes)) {
WorkorderMphModel::update((array)$workorder);
WorkorderMphJournalModel::create([
'workorderMphId' => $workorder->id,
'text' => "Dokumentation aktualisiert:\n" . implode("\n", $changes),
'create' => time(),
'createBy' => $this->user->id,
]);
}
self::returnJson(['success' => true, 'message' => 'Dokumentation aktualisiert.']);
}
//endregion
}