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

257 lines
12 KiB
PHP

<?php
class WorkorderMphCompanyController extends WorkorderMphBaseController
{
protected string $headerTitle = 'Meine MPH Arbeitsaufträge';
protected bool $createText = false;
protected array $permissionCheck = ['RMLCompany'];
protected array $columns = [
['key' => 'id', 'text' => 'Auftrags-Nr.', 'table' => ['sortable' => true]],
['key' => 'hausnummerInfo', 'text' => 'Adresse', 'modal' => false, 'table' => ['sortable' => false]],
['key' => 'wohneinheitCount', 'text' => 'WE', 'modal' => false, 'table' => ['sortable' => false]],
['key' => 'additionalInfo', 'text' => 'Notiz', 'modal' => false, 'table' => ['sortable' => true]],
['key' => 'deadlineDate', 'text' => 'Deadline', 'modal' => false, 'table' => ['filter' => 'date', 'sortable' => true]],
['key' => 'appointmentDate', 'text' => 'Termin', 'modal' => false, 'table' => ['filter' => 'date', 'sortable' => true]],
];
protected array $additionalJSVariables = ['COMPANY_ID' => '0', 'IS_COMPANY_VIEW' => true];
protected function prepareCrudConfig()
{
$hausnummerInfoColIdx = array_search('hausnummerInfo', array_column($this->columns, 'key'));
array_splice($this->columns, $hausnummerInfoColIdx + 1, 0, [$this->statusColumn]);
$company = WorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
$this->additionalJSVariables['COMPANY_ID'] = $company ? $company->id : 0;
}
protected function getAction()
{
$pagination = $this->postData['pagination'] ?? ['page' => 1, 'per_page' => 10];
$filters = $this->postData['filters'] ?? [];
$order = $this->postData['order'] ?? [];
$company = WorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
if (!$company) {
self::returnJson(['rows' => [], 'pagination' => array_merge($pagination, ['total_rows' => 0, 'total_pages' => 0, 'filtered_available' => 0])]);
return;
}
$db = FronkDB::singleton();
$fronkDbName = FRONKDB_DBNAME;
$addressDbName = defined('ADDRESSDB_DBNAME') ? ADDRESSDB_DBNAME : 'addressdb';
$whereClauses = "WHERE w.companyId = " . intval($company->id);
if (empty($filters['status'])) {
$whereClauses .= " AND w.status NOT IN ('completed', 'cancelled', 'archived')";
} else {
$whereClauses .= Helper::generateFilterCondition($filters['status'], 'w.status', true);
}
if (!empty($filters['id'])) $whereClauses .= Helper::generateFilterCondition($filters['id'], 'w.id', true);
if (!empty($filters['hausnummerInfo'])) {
$searchColumns = "str.name|hn.hausnummer|hn.stiege|plz.plz|ort.name|w.additionalInfo";
$whereClauses .= Helper::generateFilterCondition($filters['hausnummerInfo'], $searchColumns);
}
if (!empty($filters['deadlineDate'])) $whereClauses .= Helper::generateFilterCondition($filters['deadlineDate'], 'w.deadlineDate');
if (!empty($filters['appointmentDate'])) $whereClauses .= Helper::generateFilterCondition($filters['appointmentDate'], 'w.appointmentDate');
if (!empty($filters['additionalInfo'])) $whereClauses .= Helper::generateFilterCondition($filters['additionalInfo'], 'w.additionalInfo');
$sql = "
SELECT
w.id, w.status, w.deadlineDate, w.appointmentDate, w.additionalInfo,
CONCAT_WS(' ', str.name, hn.hausnummer, hn.stiege) as hausnummerInfo,
str.name as street, hn.hausnummer, hn.stiege, plz.plz, ort.name as city,
(SELECT COUNT(*) FROM `$addressDbName`.`Wohneinheit` we WHERE we.hausnummer_id = hn.id) as wohneinheitCount
FROM `$fronkDbName`.`WorkorderMph` w
LEFT JOIN `$addressDbName`.`Hausnummer` hn ON w.hausnummerId = hn.id
LEFT JOIN `$addressDbName`.`Strasse` str ON hn.strasse_id = str.id
LEFT JOIN `$addressDbName`.`Plz` plz ON hn.plz_id = plz.id
LEFT JOIN `$addressDbName`.`Ortschaft` ort ON hn.ortschaft_id = ort.id
$whereClauses
";
$orderBy = "";
if (!empty($order['key'])) {
$sortableColumns = ['id', 'status', 'deadlineDate', 'additionalInfo', 'appointmentDate'];
if (in_array($order['key'], $sortableColumns)) {
$sortOrder = (strtoupper($order['order']) === 'DESC') ? 'DESC' : 'ASC';
$orderBy = " ORDER BY " . $db->escape($order['key']) . " " . $sortOrder;
}
}
if (empty($orderBy)) $orderBy = " ORDER BY CASE WHEN w.deadlineDate IS NULL THEN 1 ELSE 0 END, w.deadlineDate ASC";
$sql .= $orderBy;
// Get total count
$countSql = "SELECT COUNT(*) as count FROM `$fronkDbName`.`WorkorderMph` w
LEFT JOIN `$addressDbName`.`Hausnummer` hn ON w.hausnummerId = hn.id
LEFT JOIN `$addressDbName`.`Strasse` str ON hn.strasse_id = str.id
LEFT JOIN `$addressDbName`.`Plz` plz ON hn.plz_id = plz.id
LEFT JOIN `$addressDbName`.`Ortschaft` ort ON hn.ortschaft_id = ort.id
$whereClauses";
$totalCount = $db->query($countSql)->fetch_assoc()['count'];
// Add pagination
if ($pagination['per_page'] !== null) {
$sql .= " LIMIT " . intval($pagination['per_page']) . " OFFSET " . intval(($pagination['page'] - 1) * $pagination['per_page']);
}
$result = $db->query($sql);
$rows = $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
self::returnJson([
'rows' => $rows,
'pagination' => [
'page' => $pagination['page'],
'per_page' => $pagination['per_page'],
'total_rows' => $totalCount,
'total_pages' => ceil($totalCount / $pagination['per_page']),
'filtered_available' => $totalCount
]
]);
}
public function getWorkorderByIdAction()
{
if (empty($this->request->id)) self::sendError("ID fehlt");
$workorder = WorkorderMphModel::get($this->request->id);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden");
self::returnJson((array)$workorder);
}
protected function scheduleAppointmentAction()
{
if (empty($this->postData['workorderId']) || empty($this->postData['appointmentDate'])) self::sendError("Erforderliche Felder fehlen.");
$workorder = WorkorderMphModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden");
if ((int)date('H', $this->postData['appointmentDate']) >= 23 || (int)date('H', $this->postData['appointmentDate']) < 1) self::sendError("Bitte geben Sie eine Uhrzeit an!");
$oldStatus = $workorder->status;
$workorder->appointmentDate = $this->postData['appointmentDate'];
$workorder->status = 'scheduled';
WorkorderMphModel::update((array)$workorder);
WorkorderMphJournalModel::create([
'workorderMphId' => $workorder->id,
'text' => 'Termin festgelegt auf: ' . date('d.m.Y H:i', $this->postData['appointmentDate']),
'statusChange' => $oldStatus !== 'scheduled' ? $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('scheduled') : null,
'create' => time(),
'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Termin erfolgreich gespeichert.']);
}
protected function rescheduleAppointmentAction()
{
if (empty($this->postData['workorderId']) || empty($this->postData['appointmentDate']) || empty($this->postData['reason'])) self::sendError("Erforderliche Felder fehlen.");
$workorder = WorkorderMphModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
if ((int)date('H', $this->postData['appointmentDate']) >= 23 || (int)date('H', $this->postData['appointmentDate']) < 1) self::sendError("Bitte geben Sie eine Uhrzeit an!");
$oldDateFormatted = $workorder->appointmentDate ? date('d.m.Y H:i', $workorder->appointmentDate) : 'N/A';
$newDateFormatted = date('d.m.Y H:i', $this->postData['appointmentDate']);
$workorder->appointmentDate = $this->postData['appointmentDate'];
WorkorderMphModel::update((array)$workorder);
WorkorderMphJournalModel::create([
'workorderMphId' => $workorder->id,
'text' => "Termin verschoben von {$oldDateFormatted} auf {$newDateFormatted}. Grund: " . $this->postData['reason'],
'create' => time(),
'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Termin erfolgreich verschoben.']);
}
protected function startWorkAction()
{
if (empty($this->postData['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderMphModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$oldStatus = $workorder->status;
$workorder->status = 'in_progress';
WorkorderMphModel::update((array)$workorder);
WorkorderMphJournalModel::create([
'workorderMphId' => $workorder->id,
'text' => 'Arbeit begonnen.',
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('in_progress'),
'create' => time(),
'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Arbeit wurde gestartet.']);
}
protected function completeWorkorderAction()
{
if (empty($this->postData['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderMphModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
// Validate that all required Wohneinheiten have notes
$wohneinheiten = WorkorderMphWohneinheitModel::getAll(['workorderMphId' => $workorder->id]);
foreach ($wohneinheiten as $we) {
if (empty($we->note)) {
self::sendError("Bitte fügen Sie für jede Wohneinheit eine Notiz hinzu, bevor Sie den Auftrag abschließen.");
}
}
$oldStatus = $workorder->status;
$workorder->status = 'documented';
WorkorderMphModel::update((array)$workorder);
WorkorderMphJournalModel::create([
'workorderMphId' => $workorder->id,
'text' => 'Arbeitsauftrag abgeschlossen und dokumentiert.',
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('documented'),
'create' => time(),
'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Arbeitsauftrag erfolgreich abgeschlossen.']);
}
protected function uploadDocumentationAction()
{
if (empty($_FILES['file']) || empty($_POST['workorderMphId'])) self::sendError("Datei und Arbeitsauftrags-ID sind erforderlich.");
$workorderMphId = intval($_POST['workorderMphId']);
$workorder = WorkorderMphModel::get($workorderMphId);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$documentType = $_POST['documentType'] ?? 'photo';
$description = $_POST['description'] ?? null;
// Upload file using mfUpload
$upload = new mfUpload($_FILES['file']);
if (!$upload->upload()) {
self::sendError("Datei-Upload fehlgeschlagen.");
}
$file = $upload->getFile();
WorkorderMphDocumentationModel::create([
'workorderMphId' => $workorderMphId,
'fileId' => $file->id,
'description' => $description,
'documentType' => $documentType,
'create' => time(),
'createBy' => $this->user->id
]);
self::returnJson(['success' => true, 'message' => 'Dokument erfolgreich hochgeladen.', 'fileId' => $file->id]);
}
protected function deleteDocumentationAction()
{
if (empty($this->postData['documentationId'])) self::sendError("Dokumentations-ID fehlt.");
$doc = WorkorderMphDocumentationModel::get($this->postData['documentationId']);
if (!$doc) self::sendError("Dokumentation nicht gefunden.");
WorkorderMphDocumentationModel::delete($doc->id);
self::returnJson(['success' => true, 'message' => 'Dokumentation gelöscht.']);
}
}