Merge branch 'ADBNetzgebiet/rework' into 'master'

new network model and mfBaseModelV2

See merge request fronk/thetool!1955
This commit is contained in:
Luca Haid
2025-12-15 14:38:51 +00:00
12 changed files with 1944 additions and 335 deletions
+121 -75
View File
@@ -1,78 +1,124 @@
<?php
class ADBNetzgebiet extends mfBaseModel {
private $gemeinden;
private $json_options;
protected function init() {
$this->db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$this->table = "Netzgebiet";
}
public function loadByExtref($extref) {
$extref = $this->db->escape(trim($extref));
if(!$extref) {
return false;
}
$res = $this->db->select("Netzgebiet", "*", "extref='$extref'");
if(!$this->db->num_rows($res)) {
return false;
}
$data = $this->db->fetch_object($res);
$this->load($data);
return true;
}
public function getOption($opt) {
$options = $this->getOptions();
if(!$options) return null;
if(property_exists($options, $opt)) {
return $options->$opt;
}
return null;
}
public function getOptions() {
if(!$this->options) {
return false;
}
$opts = json_decode($this->options);
if(json_last_error() != JSON_ERROR_NONE) {
return null;
}
return $opts;
}
public function getProperty($name) {
if($this->$name == null) {
if($name == "gemeinden") {
$gemeinden = [];
foreach(ADBGemeindeNetzgebietModel::search(["netzgebiet_id" => $this->id]) as $gem_netz) {
$g = $gem_netz->gemeinde;
if(!$g || array_key_exists($g->gemeinde_id, $gemeinden)) continue;
//var_dump($g);exit;
$gemeinden[$g->id] = $g;
}
if(count($gemeinden)) {
$this->gemeinden = $gemeinden;
}
return $this->gemeinden;
}
$classname = ucfirst($name);
$idfield = $name."_id";
$this->$name = new $classname($this->$idfield);
if($this->$name->id) {
return $this->$name;
} else {
return null;
}
}
return $this->$name;
}
require_once LIBDIR . '/mfBaseModelV2/mfBaseModelV2.php';
class ADBNetzgebietRelations {
/** @var array{id: int, name: string}[] */
public array $networks = [];
/** @var array{id: int, name: string}[] */
public array $campaigns = [];
/** @var array{id: int, name: string}[] */
public array $consentProjects = [];
}
/**
* @property-read ADBGemeinde[] $gemeinden
* @property-read ADBNetzgebietRelations $relations
*/
class ADBNetzgebiet extends mfBaseModelV2 {
protected static string $__tableName = 'Netzgebiet';
protected static string $__primaryKey = 'id';
protected static ?array $__databaseConfig = [
'host' => ADDRESSDB_DBHOST,
'user' => ADDRESSDB_DBUSER,
'pass' => ADDRESSDB_DBPASS,
'name' => ADDRESSDB_DBNAME
];
protected static array $__journalFieldMap = [
'name' => 'Name', 'extref' => 'ExtRef', 'rimo_id' => 'RIMO ID',
'source' => 'Source', 'source_id' => 'Source ID', 'borderpoly' => 'Border Polygon',
'freigabe' => 'Freigaben', 'options' => 'Options', 'create' => 'Erstellt', 'edit' => 'Bearbeitet',
];
public int $id;
public ?string $name = null;
public ?string $extref = null;
public ?string $rimo_id = null;
public ?string $source = null;
public ?string $source_id = null;
public ?string $borderpoly = null;
public ?string $freigabe = '["interest", "provision", "order", "reorder"]';
public ?string $options = '{"create_address_parts": 0, "update_freigabe": 1, "update_address": 1, "hausnummer_dont_overwrite_netzgebiet": 0, "create_preorder": 0, "preorder_only_oaid": 0, "wo_ignore_status": 0, "delete_units": 0, "mph_min_homes_tool_automatic_count": 3, "unit_create_oaid": 0}';
public int $create;
public int $edit;
private ?array $__gemeinden = null;
private ?ADBNetzgebietRelations $__relations = null;
public function __get(string $name) {
if ($name === 'gemeinden') {
if ($this->__gemeinden === null) {
$this->__gemeinden = [];
foreach (ADBGemeindeNetzgebietModel::search(["netzgebiet_id" => $this->id]) as $gem_netz) {
$g = $gem_netz->gemeinde;
if (!$g || array_key_exists($g->id, $this->__gemeinden)) continue;
$this->__gemeinden[$g->id] = $g;
}
}
return $this->__gemeinden;
}
if ($name === 'relations') {
return $this->__relations ??= $this->loadRelations();
}
return null;
}
public function loadByExtref(string $extref): bool {
$extref = trim($extref);
if (empty($extref)) return false;
$found = static::getFirst(['=extref' => $extref]);
if ($found) {
foreach (get_object_vars($found) as $key => $value) {
if (property_exists($this, $key) && !str_starts_with($key, '__')) {
$this->$key = $value;
}
}
return true;
}
return false;
}
public function getOption(string $opt): mixed {
$options = $this->getOptions();
return $options && property_exists($options, $opt) ? $options->$opt : null;
}
public function getOptions(): ?object {
if (empty($this->options)) return null;
$opts = json_decode($this->options);
return json_last_error() === JSON_ERROR_NONE ? $opts : null;
}
public function getFreigabe(): array {
if (empty($this->freigabe)) return [];
$freigabe = json_decode($this->freigabe, true);
return json_last_error() === JSON_ERROR_NONE ? $freigabe : [];
}
public function loadRelations(): ADBNetzgebietRelations {
$rel = new ADBNetzgebietRelations();
$networks = NetworkModel::search(['adb_netzgebiet_id' => $this->id]);
foreach ($networks as $network) {
$rel->networks[] = ['id' => $network->id, 'name' => $network->name];
}
$networkIds = array_column($rel->networks, 'id');
if (!empty($networkIds)) {
$campaigns = PreordercampaignModel::search(['network_id' => $networkIds]);
foreach ($campaigns as $campaign) {
$rel->campaigns[] = ['id' => $campaign->id, 'name' => $campaign->name];
}
}
$rel->consentProjects = ConstructionConsentProject::getByAdbNetzgebietId($this->id);
return $rel;
}
}
@@ -0,0 +1,137 @@
<?php
class ADBNetzgebietController extends mfBaseController {
public User $me;
private array $postData = [];
protected function init(): void {
$this->needlogin = true;
$this->me = new User();
$this->me->loadMe();
$this->layout()->set("me", $this->me);
if (!$this->me->is("Admin")) {
$this->redirect("Dashboard");
}
$rawInput = file_get_contents('php://input');
if ($rawInput) $this->postData = json_decode($rawInput, true) ?? [];
}
protected function indexAction(): void {
Helper::renderVue3($this, $this->mod, "Netzgebietverwaltung", [
"GET_URL" => $this::getUrl("ADBNetzgebiet/getNetzgebiete"),
"SAVE_URL" => $this::getUrl("ADBNetzgebiet/save"),
"HISTORY_URL" => $this::getUrl("ADBNetzgebiet/getHistory"),
"NETWORK_URL" => $this::getUrl("Network/Index"),
"NETWORK_CREATE_URL" => $this::getUrl("Network/add"),
"CAMPAIGN_URL" => $this::getUrl("Preordercampaign/edit"),
"CAMPAIGN_CREATE_URL" => $this::getUrl("Preordercampaign/add"),
"CONSENT_URL" => $this::getUrl("ConstructionConsentProject/edit"),
"CONSENT_CREATE_URL" => $this::getUrl("ConstructionConsentProject/add"),
"HIDE_PAGE_TITLE" => true,
"USER_ID" => $this->me->id,
]);
}
protected function getNetzgebieteAction(): void {
$filter = [];
if (!empty($_GET['name'])) $filter['name'] = $_GET['name'];
if (!empty($_GET['extref'])) $filter['extref'] = $_GET['extref'];
if (!empty($_GET['source'])) $filter['=source'] = $_GET['source'];
if (!empty($_GET['source_id'])) $filter['source_id'] = $_GET['source_id'];
$allNetzgebiete = ADBNetzgebiet::getAll($filter, null, 0, ['column' => 'name', 'dir' => 'ASC']);
$response = [];
foreach ($allNetzgebiete as $netzgebiet) {
$response[] = [
'netzgebiet' => $netzgebiet->toArray(),
'related' => [
'networks' => $netzgebiet->relations->networks,
'campaigns' => $netzgebiet->relations->campaigns,
'consent_projects' => $netzgebiet->relations->consentProjects
]
];
}
self::returnJson(['success' => true, 'data' => $response, 'total' => count($response)]);
}
protected function saveAction(): void {
$data = $this->postData;
if (empty($data)) { self::sendError("No data received."); return; }
$isNew = empty($data['id']);
$model = $isNew ? new ADBNetzgebiet() : ADBNetzgebiet::get($data['id']);
if (!$model) { self::sendError("Netzgebiet not found."); return; }
if (isset($data['name'])) $model->name = trim($data['name']) ?: null;
if (array_key_exists('extref', $data)) $model->extref = trim($data['extref']) ?: null;
if (array_key_exists('rimo_id', $data)) $model->rimo_id = trim($data['rimo_id']) ?: null;
if (isset($data['source'])) $model->source = $data['source'] ?: null;
if (array_key_exists('source_id', $data)) $model->source_id = trim($data['source_id']) ?: null;
if (array_key_exists('borderpoly', $data)) $model->borderpoly = $data['borderpoly'] ?: null;
if (isset($data['freigabe'])) {
$model->freigabe = is_array($data['freigabe'])
? json_encode(array_values($data['freigabe']))
: $data['freigabe'];
}
if (isset($data['options'])) {
if (is_array($data['options'])) {
$options = $data['options'];
if (isset($options['mph_min_homes_tool_automatic_count'])) {
$options['mph_min_homes_tool_automatic_count'] = (int)$options['mph_min_homes_tool_automatic_count'];
}
$boolFields = ['create_address_parts', 'update_freigabe', 'update_address',
'hausnummer_dont_overwrite_netzgebiet', 'create_preorder', 'preorder_only_oaid',
'wo_ignore_status', 'delete_units', 'unit_create_oaid'];
foreach ($boolFields as $field) {
if (isset($options[$field])) $options[$field] = $options[$field] ? 1 : 0;
}
$model->options = json_encode($options);
} else {
$model->options = $data['options'];
}
}
if (!$model->save()) { self::sendError("Failed to save Netzgebiet."); return; }
self::returnJson([
'success' => true,
'message' => $isNew ? 'Netzgebiet created.' : 'Netzgebiet saved.',
'id' => $model->getId()
]);
}
protected function getHistoryAction(): void {
$id = $_GET['id'] ?? $this->postData['id'] ?? null;
if (empty($id)) { self::sendError("ID required."); return; }
$model = ADBNetzgebiet::get($id);
if (!$model) { self::sendError("Netzgebiet not found."); return; }
$history = $model->getJournalHistory();
$userIds = array_unique(array_filter(array_column($history, 'user_id')));
$users = [];
foreach ($userIds as $userId) {
$user = new User($userId);
if ($user->id) $users[$user->id] = $user->name ?? 'User #' . $user->id;
}
foreach ($history as $entry) {
$entry->user_name = $users[$entry->user_id] ?? 'System';
}
self::returnJson(['success' => true, 'data' => $history]);
}
// TODO: Implement RIMO API check
protected function checkRimoSourceIdAction(): void {
self::returnJson(['success' => false, 'message' => "RIMO API check not available."]);
}
}
@@ -1,188 +1,4 @@
<?php
class ADBNetzgebietModel {
public $name;
public $extref;
public $source;
public $source_id;
public $rimo_id;
public $freigabe;
public $create = null;
public $edit = null;
public static function create(Array $data) {
$model = new ADBNetzgebiet();
foreach($data as $field => $value) {
if(property_exists(get_called_class(), $field)) {
$model ->$field = $value;
}
}
$me = mfValuecache::singleton()->get("me");
if(!$me) {
$me = new User();
$me->loadMe();
mfValuecache::singleton()->set("me", $me);
}
/*
if($model->create_by === null) {
$model->create_by = $me->id;
}
if($model->edit_by === null) {
$model->edit_by = $me->id;
}*/
return $model;
}
public static function getFirst($filter) {
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$where = self::getSqlFilter($filter);
$res = $db->select("Netzgebiet", "*", "$where ORDER BY name LIMIT 1");
if($db->num_rows($res)) {
$data = $db->fetch_object($res);
$item = new ADBNetzgebiet($data);
if($item->id) {
return $item;
} else {
return null;
}
}
return null;
}
public static function getAll($indexed_by_id = false) {
$items = [];
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$res = $db->select("Netzgebiet", "*", "1=1 ORDER BY name");
if($db->num_rows($res)) {
while($data = $db->fetch_object($res)) {
if($indexed_by_id) {
$items[$data->id] = new ADBNetzgebiet($data);
} else {
$items[] = new ADBNetzgebiet($data);
}
}
}
return $items;
}
public static function count($filter) {
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$where = self::getSqlFilter($filter);
$sql = "SELECT COUNT(*) as cnt FROM Netzgebiet
WHERE $where
";
$res = $db->query($sql);
if($db->num_rows($res)) {
$data = $db->fetch_object($res);
return $data->cnt;
}
return 0;
}
public static function search($filter, $limit = false) {
$items = [];
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$where = self::getSqlFilter($filter);
$sql = "SELECT Netzgebiet.* FROM Netzgebiet
WHERE $where
ORDER BY name";
mfLoghandler::singleton()->debug($sql);
if(is_array($limit) && count($limit)) {
if(is_numeric($limit['start']) && is_numeric($limit['count'])) {
$sql .= " LIMIT ".$limit['start'].", ".$limit['count'];
} elseif(is_numeric($limit['count'])) {
$sql .= " LIMIT ".$limit['count'];
}
}
$res = $db->query($sql);
if($db->num_rows($res)) {
while($data = $db->fetch_object($res)) {
$items[] = new ADBNetzgebiet($data);
}
}
return $items;
}
private static function getSqlFilter($filter) {
$where = "1=1 ";
if(array_key_exists("netzgebiet_id", $filter)) {
$netzgebiet_id = $filter['netzgebiet_id'];
if(is_numeric($netzgebiet_id)) {
$where .= " AND Netzgebiet.id=$netzgebiet_id";
} elseif(is_array($netzgebiet_id) && count($netzgebiet_id)) {
$where .= " AND Netzgebiet.id IN (". implode(",", $netzgebiet_id).")";
}
}
if(array_key_exists("name", $filter)) {
$name = FronkDB::singleton()->escape($filter['name']);
if($name) {
$where .= " AND Netzgebiet.`name` = '$name'";
}
}
if(array_key_exists("name%", $filter)) {
$name = FronkDB::singleton()->escape($filter['name%']);
if($name) {
$where .= " AND Netzgebiet.`name` LIKE '$name%'";
}
}
if(array_key_exists("extref", $filter)) {
$extref = FronkDB::singleton()->escape($filter['extref']);
if($extref) {
$where .= " AND Netzgebiet.`extref` = '$extref'";
}
}
if(array_key_exists("rimo_id", $filter)) {
$rimo_id = FronkDB::singleton()->escape($filter['rimo_id']);
if($rimo_id) {
$where .= " AND Netzgebiet.`rimo_id` LIKE '%$rimo_id%'";
}
}
if(array_key_exists("source_id", $filter)) {
$source_id = FronkDB::singleton()->escape($filter['source_id']);
if($source_id) {
$where .= " AND Netzgebiet.`source_id` LIKE '%$source_id%'";
}
}
if(array_key_exists("source", $filter)) {
$source = FronkDB::singleton()->escape($filter['source']);
if($source) {
$where .= " AND Netzgebiet.`source` = '$source'";
}
}
if(array_key_exists("borderpoly", $filter)) {
$borderpoly = $filter['borderpoly'];
if($borderpoly === true) {
$where .= " AND Netzgebiet.`borderpoly` IS NOT NULL";
} elseif($borderpoly === false || $borderpoly === null) {
$where .= " AND (Netzgebiet.`borderpoly` IS NULL OR Netzgebiet.`borderpoly` = '')";
}
}
//var_dump($filter, $where);exit;
return $where;
}
}
/** @deprecated Use ADBNetzgebiet directly */
class ADBNetzgebietModel extends ADBNetzgebiet {}
@@ -238,6 +238,20 @@ class ConstructionConsentProject extends mfBaseModel {
return $where;
}
/**
* @return array{id: int, name: string}[]
*/
public static function getByAdbNetzgebietId(int $adbNetzgebietId): array {
$db = FronkDB::singleton();
$id = $db->escape($adbNetzgebietId);
$res = $db->query(
"SELECT ccp.id, ccp.name FROM `ConstructionConsentProject` ccp
JOIN `ConstructionConsentNetwork` ccn ON ccp.id = ccn.constructionconsentproject_id
WHERE ccn.adb_netzgebiet_id = '{$id}'"
);
return $db->fetch_all_assoc($res) ?? [];
}
public static function hasFaultyOwnerEntries(int $projectId): bool {
if (empty($projectId)) return false;