Files
thetool/application/WorkorderCompany/WorkorderCompanyController.php
2026-01-27 11:20:25 +01:00

333 lines
16 KiB
PHP

<?php
class WorkorderCompanyController extends WorkorderBaseController {
protected string $headerTitle = 'Meine Arbeitsaufträge';
protected bool $createText = false;
protected array $permissionCheck = ['RMLCompany'];
protected array $columns = [
['key' => 'id', 'text' => 'Auftrags-Nr.', 'table' => ['sortable' => true]],
['key' => 'networkOwnerName', 'text' => 'Auftraggeber', 'table' => ['sortable' => false]],
['key' => 'preordercampaign_id', 'text' => 'Kampagne', 'modal' => false, 'table' => ['filter' => 'select', 'sortable' => true]],
['key' => 'preorderInfo', 'text' => 'Kunde', 'modal' => false, 'table' => ['sortable' => false]],
['key' => 'rimo_fcp_name', 'text' => 'FCP', 'modal' => false, 'table' => ['sortable' => true]],
// Status column is now inherited via prepareCrudConfig
['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', 'RML_COMPANY_MANAGER' => false];
protected function prepareCrudConfig() {
$preorderInfoColIdx = array_search('preorderInfo', array_column($this->columns, 'key'));
array_splice($this->columns, $preorderInfoColIdx + 1, 0, [$this->statusColumn]);
$company = WorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
$campaigns = Helper::getPreorderCampaignFromUser($this->user, true);
$preCamColIdx = array_search('preordercampaign_id', array_column($this->columns, 'key'));
if ($preCamColIdx !== false) {
$this->columns[$preCamColIdx]['table']['filterOptions'] = array_map(fn($c) => ['value' => $c->id, 'text' => $c->name], $campaigns);
if (!$this->user->isAdmin() && count($campaigns) === 1) {
$this->columns[$preCamColIdx]['table']['defaultFilter'] = $campaigns[0]->id;
}
}
$this->additionalJSVariables['COMPANY_ID'] = $company ? $company->id : 0;
if ($this->user->can('RMLCompanyManager')) {
$this->additionalJSVariables['RML_COMPANY_MANAGER'] = true;
}
}
public function indexAction() {
$this->archiveWorkorders();
parent::indexAction();
}
protected function logout() {
mfLoginController::staticLogout();
$this->redirect('/WorkorderCompany/Mobile');
}
public function mobileAction() {
$company = WorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
$this->layout()->setTemplate("VueViews/WorkorderCompanyPWA");
$this->layout()->set("JSGlobals", [
'BASE_PATH' => '/WorkorderCompany',
'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;
}
$workorders = WorkorderModel::getCompanyWorkorders($filters, $pagination['per_page'], ($pagination['page'] - 1) * $pagination['per_page'], $order, $company->id);
$totalCount = WorkorderModel::countCompanyWorkorders($filters, $company->id);
self::returnJson([
'rows' => $workorders,
'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 = WorkorderModel::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 = WorkorderModel::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!");
$workorder->appointmentDate = $this->postData['appointmentDate'];
$workorder->status = 'scheduled';
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id, 'text' => 'Termin festgelegt auf: ' . date('d.m.Y H:i', $this->postData['appointmentDate']),
'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 = WorkorderModel::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'];
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $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 clearAppointmentAction() {
if (empty($this->postData['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$oldDateFormatted = $workorder->appointmentDate ? date('d.m.Y H:i', $workorder->appointmentDate) : 'N/A';
$workorder->appointmentDate = null;
$workorder->status = 'assigned';
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id, 'text' => "Termin gelöscht (war: {$oldDateFormatted}).",
'create' => time(), 'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Termin erfolgreich gelöscht.']);
}
protected function requestInterventionAction() {
if (empty($this->postData['workorderId']) || empty($this->postData['journalText'])) self::sendError("Erforderliche Felder fehlen.");
$workorder = WorkorderModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$oldStatus = $workorder->status;
$workorder->status = 'intervention_required';
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id, 'text' => "Eingriff erforderlich: " . $this->postData['journalText'],
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('intervention_required'),
'create' => time(), 'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Eingriff wurde angefordert.']);
}
protected function completeWorkorderAction() {
if (empty($this->postData['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
// START ADDED VALIDATION
$tenantConfig = $this->getTenantConfigFromWorkorder($workorder->id);
if ($tenantConfig) {
if ($tenantConfig->requireCableLength && empty(trim($workorder->cableLength))) {
self::sendError("Bitte geben Sie die Kabellänge an, um den Auftrag abzuschließen.");
}
if ($tenantConfig->requireCableType && empty(trim($workorder->cableType))) {
self::sendError("Bitte geben Sie den Kabeltyp an, um den Auftrag abzuschließen.");
}
}
// END ADDED VALIDATION
$workorder->status = 'documented';
WorkorderModel::update((array)$workorder);
self::returnJson(['success' => true, 'message' => 'Arbeitsauftrag zur Prüfung eingereicht.']);
}
protected function getTenantConfigAction() {
$tenantConfig = $this->getTenantConfigFromWorkorder($this->request->workorderId);
if (!$tenantConfig) {
self::returnJson(['success' => false, 'message' => 'Keine Mandantenkonfiguration gefunden.']);
return;
}
$response = [
'success' => true,
'documentationTypes' => json_decode($tenantConfig->documentationTypes, true),
'civilEngineeringDocsRequired' => $tenantConfig->civilEngineeringDocsRequired,
'interventionTypes' => json_decode($tenantConfig->interventionTypes, true),
'requireCableLength' => $tenantConfig->requireCableLength,
'requireCableType' => $tenantConfig->requireCableType,
'showTechnicalData' => (bool)$tenantConfig->showTechnicalData,
'tiefbauSeesNormalDocs' => (bool)$tenantConfig->tiefbauSeesNormalDocs,
];
if ($tenantConfig->showTechnicalData) {
$response['technicalData'] = $this->getTechnicalData((int)$this->request->workorderId);
}
self::returnJson($response);
}
protected function uploadDocumentationAction() {
if (empty($_FILES['files']) || empty($_POST['workorderId'])) self::sendError('Erforderliche Daten fehlen.');
$workorderId = $_POST['workorderId'];
foreach ($_FILES['files']['name'] as $index => $name) {
if ($_FILES['files']['error'][$index] === UPLOAD_ERR_OK) {
$_FILES['file'] = ['name' => $name, 'type' => $_FILES['files']['type'][$index], 'tmp_name' => $_FILES['files']['tmp_name'][$index], 'error' => $_FILES['files']['error'][$index], 'size' => $_FILES['files']['size'][$index]];
try {
$uploaded = mfUpload::handleFormUpload("file", false, "/Workorder");
WorkorderDocumentationModel::create(['workorderId' => $workorderId, 'fileId' => $uploaded->id, 'description' => $_POST['description'] ?? '', 'documentType' => $_POST['documentType'] ?? 'general', 'create' => time(), 'createBy' => $this->user->id]);
} catch (Exception $e) { /* Log error if necessary */
}
}
}
$workorder = WorkorderModel::get($workorderId);
$oldStatus = $workorder->status;
$newStatus = null;
if (in_array($oldStatus, ['assigned', 'scheduled'])) {
$newStatus = 'in_progress';
} else if (in_array($oldStatus, ['correction_requested', 'problem_solved', 'civil_engineering_completed'])) {
$newStatus = 'assigned';
}
if ($newStatus) {
$workorder->status = $newStatus;
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id,
'text' => 'Status wurde nach Dokumenten-Upload automatisch auf In Beearbeitung gesetzt.',
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText($newStatus),
'create' => time(),
'createBy' => $this->user->id,
]);
}
self::returnJson(['success' => true, 'message' => "Datei(en) erfolgreich hochgeladen."]);
}
protected function deleteDocumentationAction() {
if (empty($this->postData['id'])) self::sendError("Dokumenten-ID fehlt.");
WorkorderDocumentationModel::delete($this->postData['id']);
self::returnJson(['success' => true, 'message' => 'Dokument gelöscht.']);
}
protected function updateDocumentationAction() {
if (empty($this->postData['id'])) self::sendError("Dokumenten-ID fehlt.");
$doc = WorkorderDocumentationModel::get($this->postData['id']);
if (!$doc) self::sendError("Dokument nicht gefunden.");
if (isset($this->postData['documentType'])) $doc->documentType = $this->postData['documentType'];
WorkorderModel::update((array)$doc);
self::returnJson(['success' => true, 'message' => 'Dokument aktualisiert.']);
}
protected function completeCivilEngineeringAction() {
if (empty($this->postData['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
// Re-assign to original company
if ($workorder->originalCompanyId) {
$workorder->companyId = $workorder->originalCompanyId;
$workorder->originalCompanyId = null;
}
$oldStatus = $workorder->status;
$workorder->civilEngineeringCompanyId = null;
$workorder->status = 'civil_engineering_completed';
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id, 'text' => "Tiefbau abgeschlossen.",
'statusChange' => $this->getStatusText($oldStatus) . " -> " . $this->getStatusText('civil_engineering_completed'),
'create' => time(), 'createBy' => $this->user->id,
]);
self::returnJson(['success' => true, 'message' => 'Tiefbau erfolgreich abgeschlossen.']);
}
protected function updateWorkorderDataAction() {
if (empty($this->postData['workorderId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
$workorder = WorkorderModel::get($this->postData['workorderId']);
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
$journalText = "Zusatzdaten aktualisiert:\n";
$changed = false;
if (isset($this->postData['cableLength'])) {
if ($workorder->cableLength != $this.postData['cableLength']) {
$journalText .= "Kabellänge: '{$workorder->cableLength}' -> '{$this->postData['cableLength']}'\n";
$workorder->cableLength = $this.postData['cableLength'];
$changed = true;
}
}
if (isset($this->postData['cableType'])) {
if ($workorder->cableType != $this.postData['cableType']) {
$journalText .= "Kabeltyp: '{$workorder->cableType}' -> '{$this->postData['cableType']}'\n";
$workorder->cableType = $this.postData['cableType'];
$changed = true;
}
}
if (!$changed) {
self::returnJson(['success' => true, 'message' => 'Keine Änderungen vorgenommen.']);
return;
}
WorkorderModel::update((array)$workorder);
WorkorderJournalModel::create([
'workorderId' => $workorder->id,
'text' => $journalText,
'create' => time(),
'createBy' => $this->user->id,
]);
// Re-fetch journals to return
$journals = WorkorderJournalModel::getAll(['workorderId' => intval($workorder->id)], null, 0, ['key' => 'create', 'order' => 'DESC']);
foreach ($journals as $journal) {
$journal->createByName = UserModel::getOne($journal->createBy)->name ?? 'Unbekannt';
}
self::returnJson(['success' => true, 'message' => 'Daten gespeichert.', 'journals' => $journals]);
}
//endregion
}