305 lines
13 KiB
PHP
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
|
|
}
|