updated rimotype map
This commit is contained in:
@@ -15,66 +15,66 @@ class ADBRimoFcp extends TTCrudBaseModel
|
||||
public int $create;
|
||||
public int $edit;
|
||||
|
||||
public static function getRimoFcpStatistics(): array {
|
||||
$db = self::getDB();
|
||||
$fronkDbName = defined('FRONKDB_DBNAME') ? FRONKDB_DBNAME : 'thetool';
|
||||
$addressDbName = defined('ADDRESSDB_DBNAME') ? ADDRESSDB_DBNAME : 'addressdb';
|
||||
public static function getRimoFcpStatistics(array $fcpIds = []): array {
|
||||
$fronkDbName = FRONKDB_DBNAME ?? 'thetool';
|
||||
$addressDbName = ADDRESSDB_DBNAME ?? 'addressdb';
|
||||
|
||||
$fcps = self::getAll($fcpIds ? ['id' => $fcpIds] : [], null, 0, ['key' => 'name', 'order' => 'ASC']);
|
||||
if (!$fcps) return [];
|
||||
|
||||
$fcpResultMap = [];
|
||||
foreach ($fcps as $fcp) {
|
||||
$fcpResultMap[$fcp->id] = [
|
||||
'fcp_id' => $fcp->id,
|
||||
'fcp_name' => $fcp->name,
|
||||
'fcp_rimo_id' => $fcp->rimo_id,
|
||||
'total_hausnummer_count' => 0,
|
||||
'total_wohneinheit_count' => 0,
|
||||
'total_active_preorders' => 0,
|
||||
'counts_by_rimo_type' => new stdClass(),
|
||||
];
|
||||
}
|
||||
|
||||
$idList = implode(',', array_keys($fcpResultMap));
|
||||
if (empty($idList)) return array_values($fcpResultMap);
|
||||
|
||||
$sql = "
|
||||
-- Use a Common Table Expression (CTE) to pre-calculate counts for each combination of FCP and rimo_type.
|
||||
WITH RimoTypeCounts AS (
|
||||
SELECT
|
||||
hn.fcp_id,
|
||||
-- Group NULL rimo_types into an 'UNKNOWN' category for clarity.
|
||||
COALESCE(hn.rimo_type, 'UNKNOWN') AS rimo_type,
|
||||
COUNT(DISTINCT hn.id) AS hausnummer_count,
|
||||
COUNT(DISTINCT we.id) AS wohneinheit_count,
|
||||
COUNT(DISTINCT CASE WHEN ps.code < 899 THEN p.id ELSE NULL END) AS preorder_count
|
||||
FROM
|
||||
`{$addressDbName}`.`Hausnummer` AS hn
|
||||
LEFT JOIN
|
||||
`{$addressDbName}`.`Wohneinheit` AS we ON hn.id = we.hausnummer_id
|
||||
LEFT JOIN
|
||||
`{$fronkDbName}`.`Preorder` AS p ON hn.id = p.adb_hausnummer_id
|
||||
LEFT JOIN
|
||||
`{$fronkDbName}`.`Preorderstatus` AS ps ON p.status_id = ps.id
|
||||
WHERE
|
||||
hn.fcp_id IS NOT NULL
|
||||
GROUP BY
|
||||
hn.fcp_id,
|
||||
COALESCE(hn.rimo_type, 'UNKNOWN')
|
||||
)
|
||||
-- Final SELECT statement to assemble the data for each FCP.
|
||||
SELECT
|
||||
fcp.id AS fcp_id,
|
||||
fcp.name AS fcp_name,
|
||||
fcp.rimo_id AS fcp_rimo_id,
|
||||
-- Aggregate total counts for the entire FCP.
|
||||
SUM(rtc.hausnummer_count) AS total_hausnummer_count,
|
||||
SUM(rtc.wohneinheit_count) AS total_wohneinheit_count,
|
||||
SUM(rtc.preorder_count) AS total_active_preorders,
|
||||
-- Create a single JSON object from all the rimo_type groups for the current FCP.
|
||||
JSON_OBJECTAGG(
|
||||
rtc.rimo_type,
|
||||
JSON_OBJECT(
|
||||
'hausnummer_count', rtc.hausnummer_count,
|
||||
'wohneinheit_count', rtc.wohneinheit_count,
|
||||
'preorder_count', rtc.preorder_count
|
||||
)
|
||||
) AS counts_by_rimo_type
|
||||
FROM
|
||||
`{$addressDbName}`.`RimoFcp` AS fcp
|
||||
LEFT JOIN
|
||||
RimoTypeCounts AS rtc ON fcp.id = rtc.fcp_id
|
||||
WHERE
|
||||
rtc.fcp_id IS NOT NULL
|
||||
GROUP BY
|
||||
fcp.id, fcp.name, fcp.rimo_id
|
||||
ORDER BY
|
||||
fcp.name;
|
||||
";
|
||||
SELECT
|
||||
hn.fcp_id,
|
||||
COALESCE(hn.rimo_type, 'UNKNOWN') AS rimo_type,
|
||||
COUNT(DISTINCT hn.id) AS hausnummer_count,
|
||||
COUNT(DISTINCT we.id) AS wohneinheit_count,
|
||||
COUNT(DISTINCT CASE WHEN ps.code < 899 THEN p.id END) AS preorder_count
|
||||
FROM `{$addressDbName}`.`Hausnummer` AS hn
|
||||
LEFT JOIN `{$addressDbName}`.`Wohneinheit` AS we ON hn.id = we.hausnummer_id
|
||||
LEFT JOIN `{$fronkDbName}`.`Preorder` AS p ON p.adb_hausnummer_id = hn.id
|
||||
LEFT JOIN `{$fronkDbName}`.`Preorderstatus` AS ps ON p.status_id = ps.id
|
||||
WHERE hn.fcp_id IN ({$idList})
|
||||
GROUP BY hn.fcp_id, rimo_type
|
||||
";
|
||||
|
||||
$result = $db->query($sql);
|
||||
return $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
|
||||
$result = self::getDB()->query($sql);
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$fcpId = $row['fcp_id'];
|
||||
$rimoType = $row['rimo_type'];
|
||||
|
||||
$hCount = (int)$row['hausnummer_count'];
|
||||
$wCount = (int)$row['wohneinheit_count'];
|
||||
$pCount = (int)$row['preorder_count'];
|
||||
|
||||
$fcpResultMap[$fcpId]['counts_by_rimo_type']->{$rimoType} = (object)[
|
||||
'hausnummer_count' => $hCount,
|
||||
'wohneinheit_count' => $wCount,
|
||||
'preorder_count' => $pCount,
|
||||
];
|
||||
|
||||
$fcpResultMap[$fcpId]['total_hausnummer_count'] += $hCount;
|
||||
$fcpResultMap[$fcpId]['total_wohneinheit_count'] += $wCount;
|
||||
$fcpResultMap[$fcpId]['total_active_preorders'] += $pCount;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values($fcpResultMap);
|
||||
}
|
||||
}
|
||||
@@ -1229,14 +1229,12 @@ class PreorderController extends mfBaseController {
|
||||
);
|
||||
}
|
||||
|
||||
public function getRimoFcpStatsApi() {
|
||||
$this->postData = json_decode(file_get_contents("php://input"));
|
||||
$stats = ADBRimoFcp::getRimoFcpStatistics();
|
||||
public function getRimoFcpStatsApi()
|
||||
{
|
||||
$this->postData = json_decode(file_get_contents("php://input"), true);
|
||||
$fcpIds = $this->postData['fcp_ids'] ?? [];
|
||||
$stats = ADBRimoFcp::getRimoFcpStatistics($fcpIds);
|
||||
|
||||
if (!empty($this->postData->fcp_ids)) {
|
||||
$fcpIds = (array) $this->postData->fcp_ids;
|
||||
$stats = array_filter($stats, fn($item) => in_array($item['fcp_id'], $fcpIds));
|
||||
}
|
||||
|
||||
foreach ($stats as &$item)
|
||||
if (isset($item['counts_by_rimo_type']) && is_string($item['counts_by_rimo_type']))
|
||||
@@ -1797,7 +1795,11 @@ class PreorderController extends mfBaseController {
|
||||
$this->redirect("Preorder", "Index");
|
||||
}
|
||||
|
||||
Helper::renderVue($this, "PreorderRimoTypeMap", "PreorderRimoTypeMap", ["MAPBOX_KEY" => TT_MAPBOX_TILE_API_TOKEN]);
|
||||
Helper::renderVue($this, "PreorderRimoTypeMap", "PreorderRimoTypeMap", [
|
||||
"MAPBOX_KEY" => TT_MAPBOX_TILE_API_TOKEN,
|
||||
"USER_ID" => $this->me->id,
|
||||
"ALL_USERS" => array_map(fn($u) => ["id" => $u->id, "name" => $u->name], UserModel::getAll())
|
||||
]);
|
||||
}
|
||||
|
||||
public function RimoTypeMapDataAction() {
|
||||
@@ -1810,4 +1812,130 @@ class PreorderController extends mfBaseController {
|
||||
$data = PreorderModel::getPreorderRimoTypeData($campaignId);
|
||||
self::returnJson(['success' => true, 'data' => $data]);
|
||||
}
|
||||
|
||||
public function RimoTypeMapSaveFaultsAction() {
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$campaignId = $input['campaignId'] ?? null;
|
||||
$faults = $input['faults'] ?? [];
|
||||
$allowedCampaigns = Helper::getPreorderCampaignFromUser($this->me);
|
||||
|
||||
if (!$campaignId || !in_array($campaignId, $allowedCampaigns)) self::sendError('Ungültige oder keine Kampagne ausgewählt.');
|
||||
if (!is_array($faults) || !count($faults)) self::sendError('Keine Fehlerdaten übermittelt.');
|
||||
|
||||
$campaign = new Preordercampaign($campaignId);
|
||||
if (!$campaign->id) self::sendError('Kampagne nicht gefunden.');
|
||||
|
||||
$campaign->rimo_type_map_faults = json_encode($faults);
|
||||
if (!$campaign->save()) self::sendError('Fehler beim Speichern der Fehlerdaten.');
|
||||
|
||||
self::returnJson(['success' => true, 'message' => 'Fehlerdaten erfolgreich gespeichert.']);
|
||||
}
|
||||
|
||||
public function RimoTypeMapGetFaultsAction() {
|
||||
$campaignId = $this->request->preordercampaign_id ?? null;
|
||||
$allowedCampaigns = Helper::getPreorderCampaignFromUser($this->me);
|
||||
|
||||
if (!$campaignId || !in_array($campaignId, $allowedCampaigns)) self::sendError('Ungültige oder keine Kampagne ausgewählt.');
|
||||
|
||||
$campaign = new Preordercampaign($campaignId);
|
||||
if (!$campaign->id) self::sendError('Kampagne nicht gefunden.');
|
||||
|
||||
$faults = $campaign->rimo_type_map_faults ? json_decode($campaign->rimo_type_map_faults, true) : [];
|
||||
self::returnJson(['success' => true, 'faults' => $faults]);
|
||||
}
|
||||
|
||||
protected function generateTemplate(string $templateName, array $replacements): string {
|
||||
$path = BASEDIR . "/Layout/default/{$templateName}.html";
|
||||
if (!file_exists($path)) self::sendError("Template nicht gefunden: {$templateName}");
|
||||
|
||||
$content = file_get_contents($path);
|
||||
foreach ($replacements as $key => $value) $content = str_replace("{{ {$key} }}", $value ?? '', $content);
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
public function RimoTypeMapFaultsPDFAction() {
|
||||
if (empty($this->request->preordercampaign_id)) self::sendError('Kampagnen-ID fehlt.');
|
||||
$campaignId = $this->request->preordercampaign_id;
|
||||
|
||||
if (!in_array($campaignId, Helper::getPreorderCampaignFromUser($this->me))) self::sendError('Zugriff auf diese Kampagne verweigert.');
|
||||
|
||||
$campaign = new Preordercampaign($campaignId);
|
||||
if (!$campaign->id) self::sendError('Kampagne nicht gefunden.');
|
||||
|
||||
$faults = json_decode($campaign->rimo_type_map_faults, true) ?? [];
|
||||
$allAddressesById = array_column(PreorderModel::getPreorderRimoFaultsData((int)$campaignId), null, 'hausnummer_id');
|
||||
|
||||
$faultReasonMap = [
|
||||
'building_type' => 'Gebäudetyp falsch',
|
||||
'home_count' => 'Homeanzahl falsch',
|
||||
'not_existent' => 'Gebäude nicht existent',
|
||||
'other' => 'Sonstiges',
|
||||
'graz_umgebung' => 'Ort/Gemeinde nicht existent'
|
||||
];
|
||||
|
||||
$faultyEntriesData = [];
|
||||
|
||||
foreach ($faults as $hausnummerId => $faultData) {
|
||||
if (!isset($allAddressesById[$hausnummerId])) continue;
|
||||
if (!empty($faultData['done']) && ($faultData['done'] === true || $faultData['done'] === 1 || $faultData['done'] === 'true')) continue;
|
||||
|
||||
$addressInfo = $allAddressesById[$hausnummerId];
|
||||
$reasons = array_map(fn($key) => $faultReasonMap[$key] ?? $key, $faultData['reasons'] ?? []);
|
||||
|
||||
$faultyEntriesData[$hausnummerId] = [
|
||||
'address' => $addressInfo,
|
||||
'faults' => [
|
||||
'reasons' => $reasons,
|
||||
'other' => htmlspecialchars($faultData['other'] ?? '')
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
$faultyEntries = [];
|
||||
foreach ($faultyEntriesData as $hausnummerId => $data) {
|
||||
$addressInfo = $allAddressesById[$hausnummerId];
|
||||
$faultyEntries[] = [
|
||||
'address' => $addressInfo,
|
||||
'faults' => $data['faults'],
|
||||
'addressDbLink' => "https://thetool.xinon.at/AddressDB/View?id={$hausnummerId}",
|
||||
'googleMapsLink' => "https://maps.google.com/?q={$addressInfo['gps_lat']},{$addressInfo['gps_long']}"
|
||||
];
|
||||
}
|
||||
|
||||
$tempDir = BASEDIR . "/var/temp";
|
||||
is_dir($tempDir) || mkdir($tempDir, 0775, true);
|
||||
|
||||
$replacements = [
|
||||
'basedir' => BASEDIR,
|
||||
'campaignName' => htmlspecialchars($campaign->name),
|
||||
'creationDate' => date("d.m.Y"),
|
||||
];
|
||||
|
||||
$headerFile = tempnam($tempDir, 'pdf_header_') . '.html';
|
||||
$footerFile = tempnam($tempDir, 'pdf_footer_') . '.html';
|
||||
file_put_contents($headerFile, $this->generateTemplate('Preorder/PDF_HEADER', $replacements));
|
||||
file_put_contents($footerFile, $this->generateTemplate('Preorder/PDF_FOOTER', $replacements));
|
||||
|
||||
$pdf = new PdfForm("Preorder/PDF_MAIN", [
|
||||
"campaignName" => $campaign->name,
|
||||
"faultyEntries" => $faultyEntries,
|
||||
]);
|
||||
|
||||
$options = "--header-html {$headerFile} --footer-html {$footerFile} --margin-top 35 --margin-bottom 25";
|
||||
$filename = $pdf->render($options);
|
||||
|
||||
unlink($headerFile);
|
||||
unlink($footerFile);
|
||||
|
||||
if (!file_exists($filename)) self::sendError('Generierte PDF-Datei nicht gefunden.');
|
||||
|
||||
$outputFilename = "Fehlerprotokoll_" . preg_replace('/[^a-zA-Z0-9_-]/', '_', $campaign->name) . ".pdf";
|
||||
header('Content-Type: application/pdf');
|
||||
header('Content-Disposition: inline; filename="' . $outputFilename . '"');
|
||||
header('Content-Length: ' . filesize($filename));
|
||||
readfile($filename);
|
||||
unlink($filename);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1357,7 +1357,7 @@ ORDER BY
|
||||
$sql = "
|
||||
SELECT
|
||||
h.id AS hausnummer_id, h.gps_lat, h.gps_long, h.rimo_type, h.rimo_op_state, h.rimo_ex_state, h.hausnummer,
|
||||
s.name AS strasse_name, plz.plz AS plz_name, o.name AS ortschaft_name,
|
||||
s.name AS strasse_name, plz.plz AS plz_name, o.name AS ortschaft_name, h.rimo_id,
|
||||
COUNT(DISTINCT we.id) AS wohneinheit_count,
|
||||
COUNT(DISTINCT ps.id) AS preorder_count
|
||||
FROM `{$addressDbName}`.`Hausnummer` AS h
|
||||
@@ -1379,4 +1379,38 @@ ORDER BY
|
||||
$result = $db->query($sql);
|
||||
return $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
|
||||
}
|
||||
|
||||
public static function getPreorderRimoFaultsData(int $campaignId): array {
|
||||
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
|
||||
$fronkDbName = defined('FRONKDB_DBNAME') ? FRONKDB_DBNAME : 'thetool';
|
||||
$addressDbName = defined('ADDRESSDB_DBNAME') ? ADDRESSDB_DBNAME : 'addressdb';
|
||||
$safeCampaignId = (int)$campaignId;
|
||||
|
||||
$sql = "
|
||||
SELECT
|
||||
h.id AS hausnummer_id, h.rimo_id as extref, h.gps_lat, h.gps_long, h.rimo_type,
|
||||
h.rimo_op_state, h.rimo_ex_state, h.hausnummer,
|
||||
s.name AS strasse_name,
|
||||
plz.plz AS plz_name,
|
||||
o.name AS ortschaft_name,
|
||||
g.name as gemeinde_name,
|
||||
COUNT(DISTINCT we.id) AS wohneinheit_count
|
||||
FROM `{$addressDbName}`.`Hausnummer` AS h
|
||||
LEFT JOIN `{$addressDbName}`.`Wohneinheit` AS we ON h.id = we.hausnummer_id
|
||||
LEFT JOIN `{$addressDbName}`.`Strasse` AS s ON h.strasse_id = s.id
|
||||
LEFT JOIN `{$addressDbName}`.`Gemeinde` AS g ON s.gemeinde_id = g.id
|
||||
LEFT JOIN `{$addressDbName}`.`Plz` AS plz ON h.plz_id = plz.id
|
||||
LEFT JOIN `{$addressDbName}`.`Ortschaft` AS o ON h.ortschaft_id = o.id
|
||||
WHERE h.netzgebiet_id = (
|
||||
SELECT n.adb_netzgebiet_id FROM `{$fronkDbName}`.`Preordercampaign` pc
|
||||
JOIN `{$fronkDbName}`.`Network` n ON pc.network_id = n.id
|
||||
WHERE pc.id = {$safeCampaignId}
|
||||
) AND h.gps_lat IS NOT NULL AND h.gps_long IS NOT NULL
|
||||
GROUP BY h.id
|
||||
ORDER BY s.name, h.hausnummer
|
||||
";
|
||||
|
||||
$result = $db->query($sql);
|
||||
return $result ? $result->fetch_all(MYSQLI_ASSOC) : [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user