Workorder mph/improve
This commit is contained in:
@@ -17,14 +17,10 @@ class RadiusController extends mfBaseController {
|
||||
protected function indexAction() {
|
||||
$this->layout()->set('additionalJS', ["plugins/chart.js/chart.4.4.6.js", "plugins/chart.js/chartjs-adapter-moment.min.js"]);
|
||||
|
||||
$allowedAcsUserIds = [9, 13, 25, 65, 135, 145, 178];
|
||||
$acsEnabled = in_array($this->me->id, $allowedAcsUserIds);
|
||||
|
||||
Helper::renderVue3($this, $this->mod, "Radius", [
|
||||
'CAN_BILLING' => $this->me->can("Billing"),
|
||||
'HIDE_PAGE_TITLE' => true,
|
||||
'USER_ID' => $this->me->id,
|
||||
'ACS_ENABLED' => $acsEnabled
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -286,13 +282,14 @@ class RadiusController extends mfBaseController {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
$this->log->debug("genieacsRemoteAccessAction", ['deviceId' => $deviceId]);
|
||||
$forceRecreate = $input['forceRecreate'] ?? false;
|
||||
$this->log->debug("genieacsRemoteAccessAction", ['deviceId' => $deviceId, 'forceRecreate' => $forceRecreate]);
|
||||
|
||||
if (!$deviceId) self::sendError("Device ID is required");
|
||||
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$result = $acs->createRemoteUser($deviceId);
|
||||
|
||||
$result = $acs->createRemoteUser($deviceId, $forceRecreate);
|
||||
|
||||
if ($result) {
|
||||
self::returnJson(['success' => true] + $result);
|
||||
} else {
|
||||
@@ -304,19 +301,71 @@ class RadiusController extends mfBaseController {
|
||||
}
|
||||
}
|
||||
|
||||
protected function genieacsEventLogAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
$this->log->debug("genieacsEventLogAction", ['deviceId' => $deviceId]);
|
||||
|
||||
if (!$deviceId) self::sendError("Device ID is required");
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$creds = $acs->createRemoteUser($deviceId);
|
||||
|
||||
if (!$creds) self::sendError("Could not obtain credentials for FritzBox");
|
||||
|
||||
$url = "http://acs.xinon.at:5000/read-fritz-eventlog";
|
||||
$apiKey = "2H9zWrgxPEJL9MZ1yTGtWh16cPCu0AsQ";
|
||||
|
||||
$data = json_encode([
|
||||
'fritz_ip' => $creds['ip'],
|
||||
'fritz_port' => "9090",
|
||||
'fritz_user' => $creds['username'],
|
||||
'fritz_pass' => $creds['password']
|
||||
]);
|
||||
|
||||
$opts = [
|
||||
"http" => [
|
||||
"method" => "POST",
|
||||
"header" => "Content-Type: application/json\r\n" .
|
||||
"X-API-Key: " . $apiKey . "\r\n" .
|
||||
"Content-Length: " . strlen($data) . "\r\n",
|
||||
"content" => $data,
|
||||
"timeout" => 60
|
||||
]
|
||||
];
|
||||
|
||||
$context = stream_context_create($opts);
|
||||
$response = file_get_contents($url, false, $context);
|
||||
|
||||
if ($response) {
|
||||
$json = json_decode($response, true);
|
||||
if ($json && isset($json['data'])) {
|
||||
self::returnJson(['success' => true, 'events' => $json['data']]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self::sendError("Failed to fetch event log");
|
||||
} catch (Exception $e) {
|
||||
$this->log->debug("Event Log Error", ['error' => $e->getMessage()]);
|
||||
self::sendError("Error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected function genieacsNetworkStructureAction() {
|
||||
try {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$deviceId = $input['deviceId'] ?? null;
|
||||
$this->log->debug("genieacsNetworkStructureAction", ['deviceId' => $deviceId]);
|
||||
|
||||
|
||||
if (!$deviceId) self::sendError("Device ID is required");
|
||||
|
||||
|
||||
$acs = $this->getGenieACS();
|
||||
$creds = $acs->createRemoteUser($deviceId);
|
||||
|
||||
|
||||
if (!$creds) self::sendError("Could not obtain credentials for FritzBox");
|
||||
|
||||
|
||||
$url = "http://acs.xinon.at:5000/read-fritz";
|
||||
$apiKey = "2H9zWrgxPEJL9MZ1yTGtWh16cPCu0AsQ";
|
||||
|
||||
|
||||
@@ -8,11 +8,13 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
|
||||
protected array $columns = [
|
||||
['key' => 'id', 'text' => 'Auftrags-Nr.', 'table' => ['sortable' => true, 'filter' => 'numberRange']],
|
||||
['key' => 'netOwnerId', 'text' => 'Netzeigentümer', 'modal' => false, 'table' => ['filter' => 'select', 'sortable' => false], 'required' => false],
|
||||
['key' => 'hausnummerInfo', 'text' => 'Adresse', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => false]],
|
||||
['key' => 'netzgebietName', 'text' => 'Netzgebiet', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => true]],
|
||||
['key' => 'companyName', 'text' => 'Firma', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => true]],
|
||||
['key' => 'wohneinheitCount', 'text' => 'WE', 'modal' => false, 'table' => ['sortable' => false]],
|
||||
['key' => 'additionalInfo', 'text' => 'Notiz', 'modal' => false, 'table' => ['sortable' => true]],
|
||||
['key' => 'netzgebietName', 'text' => 'Netzgebiet', 'modal' => false, 'table' => ['filter' => 'select', 'sortable' => false]],
|
||||
['key' => 'rimoFcpName', 'text' => 'FCP', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => false]],
|
||||
['key' => 'companyName', 'text' => 'Firma', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => false]],
|
||||
['key' => 'wohneinheitCount', 'text' => 'WE', 'modal' => false, 'table' => ['sortable' => true, 'filter' => 'numberRange']],
|
||||
['key' => 'additionalInfo', 'text' => 'Notiz', 'modal' => false, 'table' => ['sortable' => false]],
|
||||
['key' => 'deadlineDate', 'text' => 'Deadline', 'modal' => false, 'table' => ['filter' => 'date', 'sortable' => true]],
|
||||
['key' => 'appointmentDate', 'text' => 'Termin', 'modal' => false, 'table' => ['filter' => 'date', 'sortable' => true]],
|
||||
];
|
||||
@@ -21,11 +23,49 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
{
|
||||
$hausnummerInfoColIdx = array_search('hausnummerInfo', array_column($this->columns, 'key'));
|
||||
array_splice($this->columns, $hausnummerInfoColIdx + 1, 0, [$this->statusColumn]);
|
||||
|
||||
// Handle netOwnerId column - only visible for admins
|
||||
$netOwnerColIdx = array_search('netOwnerId', array_column($this->columns, 'key'));
|
||||
if ($netOwnerColIdx !== false) {
|
||||
if ($this->user->isAdmin()) {
|
||||
$netOwners = Helper::getMphNetworkOwners();
|
||||
$this->columns[$netOwnerColIdx]['table']['filterOptions'] = array_map(fn($o) => ['value' => $o->id, 'text' => $o->company], $netOwners);
|
||||
} else {
|
||||
$this->columns[$netOwnerColIdx]['table'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Populate netzgebiet filter options
|
||||
$netzgebietColIdx = array_search('netzgebietName', array_column($this->columns, 'key'));
|
||||
if ($netzgebietColIdx !== false) {
|
||||
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
|
||||
|
||||
// Apply network ownership filtering
|
||||
$netzgebietFilter = "";
|
||||
if (!$this->user->isAdmin()) {
|
||||
$allowedNetzgebietIds = Helper::getADBNetworksFromUser($this->user);
|
||||
if (!empty($allowedNetzgebietIds)) {
|
||||
$escapedIds = array_map(fn($id) => $db->escape($id), $allowedNetzgebietIds);
|
||||
$netzgebietFilter = " AND ng.id IN (" . implode(',', $escapedIds) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
$fronkDbName = FRONKDB_DBNAME;
|
||||
$sql = "SELECT DISTINCT ng.id, ng.name FROM Netzgebiet ng
|
||||
INNER JOIN Hausnummer hn ON ng.id = hn.netzgebiet_id
|
||||
INNER JOIN `$fronkDbName`.`WorkorderMph` wm ON wm.hausnummerId = hn.id
|
||||
WHERE ng.name IS NOT NULL AND ng.name != ''
|
||||
$netzgebietFilter
|
||||
ORDER BY ng.name ASC";
|
||||
$result = $db->query($sql);
|
||||
$netzgebiete = $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
|
||||
$this->columns[$netzgebietColIdx]['table']['filterOptions'] = array_map(fn($ng) => ['value' => $ng['id'], 'text' => $ng['name']], $netzgebiete);
|
||||
}
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
$this->createWorkordersFromHausnummer();
|
||||
// Note: Workorder creation is now handled by cronjob script: scripts/workorder-mph-create-from-hausnummer.php
|
||||
parent::indexAction();
|
||||
}
|
||||
|
||||
@@ -41,6 +81,18 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
|
||||
$whereClauses = "WHERE 1=1";
|
||||
|
||||
// Apply network ownership filtering (similar to WorkorderAdmin)
|
||||
if (!$this->user->isAdmin()) {
|
||||
$allowedNetzgebietIds = Helper::getADBNetworksFromUser($this->user);
|
||||
if (!empty($allowedNetzgebietIds)) {
|
||||
$escapedIds = array_map(fn($id) => $db->escape($id), $allowedNetzgebietIds);
|
||||
$whereClauses .= " AND hn.netzgebiet_id IN (" . implode(',', $escapedIds) . ")";
|
||||
} else {
|
||||
// User has no networks assigned, show no results
|
||||
$whereClauses .= " AND 1=0";
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($filters['status'])) {
|
||||
$whereClauses .= " AND w.status NOT IN ('completed', 'cancelled', 'archived')";
|
||||
} else {
|
||||
@@ -48,12 +100,15 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
}
|
||||
|
||||
if (!empty($filters['id'])) $whereClauses .= Helper::generateFilterCondition($filters['id'], 'w.id', true);
|
||||
if (!empty($filters['netOwnerId'])) $whereClauses .= Helper::generateFilterCondition($filters['netOwnerId'], 'n.owner_id');
|
||||
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['netzgebietName'])) $whereClauses .= Helper::generateFilterCondition($filters['netzgebietName'], 'ng.name');
|
||||
if (!empty($filters['netzgebietName'])) $whereClauses .= Helper::generateFilterCondition($filters['netzgebietName'], 'ng.id');
|
||||
if (!empty($filters['rimoFcpName'])) $whereClauses .= Helper::generateFilterCondition($filters['rimoFcpName'], 'hn.rimo_fcp_name');
|
||||
if (!empty($filters['companyName'])) $whereClauses .= Helper::generateFilterCondition($filters['companyName'], 'c.name');
|
||||
if (!empty($filters['wohneinheitCount'])) $whereClauses .= Helper::generateFilterCondition($filters['wohneinheitCount'], '(SELECT COUNT(*) FROM `' . $addressDbName . '`.`Wohneinheit` we WHERE we.hausnummer_id = hn.id)', true);
|
||||
if (!empty($filters['deadlineDate'])) $whereClauses .= Helper::generateFilterCondition($filters['deadlineDate'], 'w.deadlineDate');
|
||||
if (!empty($filters['additionalInfo'])) $whereClauses .= Helper::generateFilterCondition($filters['additionalInfo'], 'w.additionalInfo');
|
||||
|
||||
@@ -63,7 +118,9 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
IFNULL(c.name, 'Nicht zugewiesen') as companyName,
|
||||
CONCAT_WS(' ', str.name, hn.hausnummer, hn.stiege) as hausnummerInfo,
|
||||
str.name as street, hn.hausnummer, hn.stiege, plz.plz, ort.name as city,
|
||||
IFNULL(ng.name, '-') as netzgebietName,
|
||||
ng.id as netzgebietName,
|
||||
n.owner_id as netOwnerId,
|
||||
hn.rimo_fcp_name as rimoFcpName,
|
||||
(SELECT COUNT(*) FROM `$addressDbName`.`Wohneinheit` we WHERE we.hausnummer_id = hn.id) as wohneinheitCount
|
||||
FROM `$fronkDbName`.`WorkorderMph` w
|
||||
LEFT JOIN `$fronkDbName`.`WorkorderCompany` c ON w.companyId = c.id
|
||||
@@ -72,12 +129,13 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
LEFT JOIN `$addressDbName`.`Plz` plz ON hn.plz_id = plz.id
|
||||
LEFT JOIN `$addressDbName`.`Ortschaft` ort ON hn.ortschaft_id = ort.id
|
||||
LEFT JOIN `$addressDbName`.`Netzgebiet` ng ON hn.netzgebiet_id = ng.id
|
||||
LEFT JOIN `$fronkDbName`.`Network` n ON n.adb_netzgebiet_id = ng.id
|
||||
$whereClauses
|
||||
";
|
||||
|
||||
$orderBy = "";
|
||||
if (!empty($order['key'])) {
|
||||
$sortableColumns = ['id', 'status', 'deadlineDate', 'companyName', 'additionalInfo', 'appointmentDate', 'netzgebietName'];
|
||||
$sortableColumns = ['id', 'status', 'deadlineDate', 'appointmentDate', 'wohneinheitCount'];
|
||||
if (in_array($order['key'], $sortableColumns)) {
|
||||
$sortOrder = (strtoupper($order['order']) === 'DESC') ? 'DESC' : 'ASC';
|
||||
$orderBy = " ORDER BY " . $db->escape($order['key']) . " " . $sortOrder;
|
||||
@@ -95,8 +153,9 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
LEFT JOIN `$addressDbName`.`Plz` plz ON hn.plz_id = plz.id
|
||||
LEFT JOIN `$addressDbName`.`Ortschaft` ort ON hn.ortschaft_id = ort.id
|
||||
LEFT JOIN `$addressDbName`.`Netzgebiet` ng ON hn.netzgebiet_id = ng.id
|
||||
LEFT JOIN `$fronkDbName`.`Network` n ON n.adb_netzgebiet_id = ng.id
|
||||
$whereClauses";
|
||||
$totalCount = $db->query($countSql)->fetch_assoc()['count'];
|
||||
$totalCount = (int)$db->query($countSql)->fetch_assoc()['count'];
|
||||
|
||||
// Add pagination
|
||||
if ($pagination['per_page'] !== null) {
|
||||
@@ -109,10 +168,10 @@ class WorkorderMphAdminController extends WorkorderMphBaseController
|
||||
self::returnJson([
|
||||
'rows' => $rows,
|
||||
'pagination' => [
|
||||
'page' => $pagination['page'],
|
||||
'per_page' => $pagination['per_page'],
|
||||
'page' => (int)$pagination['page'],
|
||||
'per_page' => (int)$pagination['per_page'],
|
||||
'total_rows' => $totalCount,
|
||||
'total_pages' => ceil($totalCount / $pagination['per_page']),
|
||||
'total_pages' => (int)ceil($totalCount / $pagination['per_page']),
|
||||
'filtered_available' => $totalCount
|
||||
]
|
||||
]);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class WorkorderMphBaseController extends TTCrud
|
||||
{
|
||||
protected array $statusColumn = [
|
||||
'key' => 'status', 'text' => 'Status', 'modal' => false, 'table' => ['filter' => 'iconSelect', 'filterOptions' => [
|
||||
'key' => 'status', 'text' => 'Status', 'modal' => false, 'table' => ['filter' => 'iconSelect', 'sortable' => false, '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'],
|
||||
@@ -523,7 +523,10 @@ class WorkorderMphBaseController extends TTCrud
|
||||
$newValue = $post[$field] ? 1 : 0;
|
||||
if ($oldValue !== $newValue) {
|
||||
$workorder->$field = $newValue;
|
||||
$changes[] = "$fieldLabel: " . ($newValue ? 'ja' : 'nein');
|
||||
// Only log changes where newValue is 'ja' or oldValue was 'ja' (changing from yes to no)
|
||||
if ($newValue === 1 || $oldValue === 1) {
|
||||
$changes[] = "$fieldLabel: " . ($newValue ? 'ja' : 'nein');
|
||||
}
|
||||
|
||||
// Check for FTTx Location mit Leerrohr versorgt
|
||||
if ($field === 'fttxLocationSupplied' && $newValue === 1) {
|
||||
|
||||
@@ -7,10 +7,11 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
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' => 'id', 'text' => 'Auftrags-Nr.', 'table' => ['sortable' => true, 'filter' => 'numberRange']],
|
||||
['key' => 'hausnummerInfo', 'text' => 'Adresse', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => false]],
|
||||
['key' => 'netzgebietName', 'text' => 'Netzgebiet', 'modal' => false, 'table' => ['filter' => 'select', 'sortable' => false]],
|
||||
['key' => 'rimoFcpName', 'text' => 'FCP', 'modal' => false, 'table' => ['filter' => 'search', 'sortable' => false]],
|
||||
['key' => 'additionalInfo', 'text' => 'Notiz', 'modal' => false, 'table' => ['sortable' => false]],
|
||||
['key' => 'deadlineDate', 'text' => 'Deadline', 'modal' => false, 'table' => ['filter' => 'date', 'sortable' => true]],
|
||||
['key' => 'appointmentDate', 'text' => 'Termin', 'modal' => false, 'table' => ['filter' => 'date', 'sortable' => true]],
|
||||
];
|
||||
@@ -23,6 +24,22 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
|
||||
$company = WorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
|
||||
$this->additionalJSVariables['COMPANY_ID'] = $company ? $company->id : 0;
|
||||
|
||||
// Populate netzgebiet filter options for this company's workorders
|
||||
$netzgebietColIdx = array_search('netzgebietName', array_column($this->columns, 'key'));
|
||||
if ($netzgebietColIdx !== false && $company) {
|
||||
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
|
||||
$fronkDbName = FRONKDB_DBNAME;
|
||||
|
||||
$sql = "SELECT DISTINCT ng.id, ng.name FROM Netzgebiet ng
|
||||
INNER JOIN Hausnummer hn ON ng.id = hn.netzgebiet_id
|
||||
INNER JOIN `$fronkDbName`.`WorkorderMph` wm ON wm.hausnummerId = hn.id
|
||||
WHERE ng.name IS NOT NULL AND ng.name != '' AND wm.companyId = " . intval($company->id) . "
|
||||
ORDER BY ng.name ASC";
|
||||
$result = $db->query($sql);
|
||||
$netzgebiete = $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
|
||||
$this->columns[$netzgebietColIdx]['table']['filterOptions'] = array_map(fn($ng) => ['value' => $ng['id'], 'text' => $ng['name']], $netzgebiete);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getAction()
|
||||
@@ -54,6 +71,8 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
$searchColumns = "str.name|hn.hausnummer|hn.stiege|plz.plz|ort.name|w.additionalInfo";
|
||||
$whereClauses .= Helper::generateFilterCondition($filters['hausnummerInfo'], $searchColumns);
|
||||
}
|
||||
if (!empty($filters['netzgebietName'])) $whereClauses .= Helper::generateFilterCondition($filters['netzgebietName'], 'ng.id');
|
||||
if (!empty($filters['rimoFcpName'])) $whereClauses .= Helper::generateFilterCondition($filters['rimoFcpName'], 'hn.rimo_fcp_name');
|
||||
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');
|
||||
@@ -63,18 +82,21 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
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,
|
||||
ng.id as netzgebietName,
|
||||
hn.rimo_fcp_name as rimoFcpName,
|
||||
(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
|
||||
LEFT JOIN `$addressDbName`.`Netzgebiet` ng ON hn.netzgebiet_id = ng.id
|
||||
$whereClauses
|
||||
";
|
||||
|
||||
$orderBy = "";
|
||||
if (!empty($order['key'])) {
|
||||
$sortableColumns = ['id', 'status', 'deadlineDate', 'additionalInfo', 'appointmentDate'];
|
||||
$sortableColumns = ['id', 'status', 'deadlineDate', 'appointmentDate'];
|
||||
if (in_array($order['key'], $sortableColumns)) {
|
||||
$sortOrder = (strtoupper($order['order']) === 'DESC') ? 'DESC' : 'ASC';
|
||||
$orderBy = " ORDER BY " . $db->escape($order['key']) . " " . $sortOrder;
|
||||
@@ -90,8 +112,9 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
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
|
||||
LEFT JOIN `$addressDbName`.`Netzgebiet` ng ON hn.netzgebiet_id = ng.id
|
||||
$whereClauses";
|
||||
$totalCount = $db->query($countSql)->fetch_assoc()['count'];
|
||||
$totalCount = (int)$db->query($countSql)->fetch_assoc()['count'];
|
||||
|
||||
// Add pagination
|
||||
if ($pagination['per_page'] !== null) {
|
||||
@@ -104,10 +127,10 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
self::returnJson([
|
||||
'rows' => $rows,
|
||||
'pagination' => [
|
||||
'page' => $pagination['page'],
|
||||
'per_page' => $pagination['per_page'],
|
||||
'page' => (int)$pagination['page'],
|
||||
'per_page' => (int)$pagination['per_page'],
|
||||
'total_rows' => $totalCount,
|
||||
'total_pages' => ceil($totalCount / $pagination['per_page']),
|
||||
'total_pages' => (int)ceil($totalCount / $pagination['per_page']),
|
||||
'filtered_available' => $totalCount
|
||||
]
|
||||
]);
|
||||
@@ -190,14 +213,6 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
$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);
|
||||
@@ -253,4 +268,34 @@ class WorkorderMphCompanyController extends WorkorderMphBaseController
|
||||
WorkorderMphDocumentationModel::delete($doc->id);
|
||||
self::returnJson(['success' => true, 'message' => 'Dokumentation gelöscht.']);
|
||||
}
|
||||
|
||||
protected function updateAdditionalInfoAction()
|
||||
{
|
||||
if (empty($this->postData['workorderMphId'])) self::sendError("Arbeitsauftrags-ID fehlt.");
|
||||
|
||||
$workorder = WorkorderMphModel::get($this->postData['workorderMphId']);
|
||||
if (!$workorder) self::sendError("Arbeitsauftrag nicht gefunden.");
|
||||
|
||||
// Verify company access
|
||||
$company = WorkorderCompanyModel::getFirst(['addressId' => $this->user->address_id]);
|
||||
if (!$company || $workorder->companyId != $company->id) {
|
||||
self::sendError("Keine Berechtigung für diesen Arbeitsauftrag.");
|
||||
}
|
||||
|
||||
$oldInfo = $workorder->additionalInfo;
|
||||
$newInfo = $this->postData['additionalInfo'] ?? '';
|
||||
$workorder->additionalInfo = $newInfo;
|
||||
WorkorderMphModel::update((array)$workorder);
|
||||
|
||||
if ($oldInfo !== $newInfo) {
|
||||
WorkorderMphJournalModel::create([
|
||||
'workorderMphId' => $workorder->id,
|
||||
'text' => "Notiz geändert: " . ($newInfo ?: '(leer)'),
|
||||
'create' => time(),
|
||||
'createBy' => $this->user->id,
|
||||
]);
|
||||
}
|
||||
|
||||
self::returnJson(['success' => true, 'message' => 'Notiz aktualisiert.', 'newInfo' => $newInfo]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ class WorkorderTenantConfigModel extends TTCrudBaseModel {
|
||||
public int $civilEngineeringDocsRequired;
|
||||
public int $requireCableLength;
|
||||
public int $requireCableType;
|
||||
public int $enableWorkorder;
|
||||
public int $enableWorkorderMph;
|
||||
public int $create;
|
||||
public int $createBy;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user