AddressDB Status change UI

This commit is contained in:
Frank Schubert
2024-12-06 13:35:55 +01:00
parent 40e9aaf505
commit 3a7b356b30
7 changed files with 593 additions and 10 deletions

View File

@@ -9,8 +9,8 @@
<div class="page-title-box">
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);"><?=MFAPPNAME_SLUG?></a></li>
<li class="breadcrumb-item"><a href="javascript: void(0);">GWR / AddressDB</a></li>
<li class="breadcrumb-item"><a href="<?=self::getUrl("Dashboard")?>"><?=MFAPPNAME_SLUG?></a></li>
<li class="breadcrumb-item"><a href="<?=self::getUrl("AddressDB")?>">GWR / AddressDB</a></li>
<li class="breadcrumb-item active"><?=$address->strasse->name?> <?=$address->hausnummer?>, <?=$address->plz->plz?> <?=$address->ortschaft->name?></li>
</ol>
</div>
@@ -66,12 +66,22 @@
</tr><tr>
<td colspan="2"><h4>Status</h4></td>
</tr><tr>
<th>Status Code</th>
<td class="text-monospace"><?=$address->status->code?></td>
</tr><tr>
<th>Status Text</th>
<td class="text-monospace"><?=$address->status->name?></td>
</tr><tr>
<th>Status</th>
<td class="text-monospace">
<span id="addressstatus-<?=$address->id?>-text" data-status-id="<?=$address->status_id?>"><span id="addressstatus-<?=$address->id?>-statustext"><?=$address->status->code?> - <?=$address->status->name?></span> <a href="#" onclick="return toggleAddressStatusControl(<?=$address->id?>)"><i class="fas fa-fw fa-edit"></i></a></span>
<div class="input-group" id="addressstatus-<?=$address->id?>-input" style="display:none">
<select class="form-control">
<?php foreach(ADBStatusModel::search(["!type" => "wohneinheit"]) as $status): ?>
<option value="<?=$status->id?>" <?=($address->status_id == $status->id) ? "selected='selected'" : ""?>><?=$status->code?> - <?=$status->name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-append">
<button type="button" class="btn btn-primary" title="Speichern" onclick="saveAddressStatusControl(<?=$address->id?>)"><i class="fas fa-check"></i></button>
<button type="button" class="btn btn-secondary" title="Abbrechen" onclick="toggleAddressStatusControl(<?=$address->id?>)"><i class="fas fa-times"></i></button>
</div>
</div>
</td>
</tr><tr>
<th>Statusflags</th>
<td>
<table class="table table-sm table-bordered table-striped bg-white">
@@ -158,7 +168,20 @@
<?php endif; ?>
<?php endif; ?>
</td>
<td class="text-monospace"><?=$unit->status->code?> - <?=$unit->status->name?></td>
<td id="unit-<?=$unit->id?>-status" class="text-monospace">
<span id="unitstatus-<?=$unit->id?>-text" data-status-id="<?=$unit->status_id?>"><span id="unitstatus-<?=$unit->id?>-statustext"><?=$unit->status->code?> - <?=$unit->status->name?></span> <a href="#" onclick="return toggleUnitStatusControl(<?=$unit->id?>)"><i class="fas fa-fw fa-edit"></i></a></span>
<div class="input-group" id="unitstatus-<?=$unit->id?>-input" style="display:none">
<select class="form-control">
<?php foreach(ADBStatusModel::search(["!type" => "hausnummer"]) as $status): ?>
<option value="<?=$status->id?>" <?=($unit->status_id == $status->id) ? "selected='selected'" : ""?>><?=$status->code?> - <?=$status->name?></option>
<?php endforeach; ?>
</select>
<div class="input-group-append">
<button type="button" class="btn btn-primary" title="Speichern" onclick="saveUnitStatusControl(<?=$unit->id?>)"><i class="fas fa-check"></i></button>
<button type="button" class="btn btn-secondary" title="Abbrechen" onclick="toggleUnitStatusControl(<?=$unit->id?>)"><i class="fas fa-times"></i></button>
</div>
</div>
</td>
<td><?=((string)$unit) ? "<strong>".(string)$unit."</strong>" : ""?></td>
<td><?=($unit->extref) ? "[".$unit->extref."]" : ""?></td>
<td title="Anzahl Bestellungen"><?=PreorderModel::countActive(["adb_wohneinheit_id" => $unit->id])?></td>
@@ -183,4 +206,148 @@
</div>
</div>
<script>
function toggleAddressStatusControl(pid) {
// set select to current status id
$("#addressstatus-" + pid + "-input select").val($("#addressstatus-" + pid + "-text").data("status-id"));
// toggle controls
$("#addressstatus-" + pid + "-text").toggle();
$("#addressstatus-" + pid + "-input").toggle();
return false;
}
function toggleUnitStatusControl(pid) {
// set select to current status id
$("#unitstatus-" + pid + "-input select").val($("#unitstatus-" + pid + "-text").data("status-id"));
// toggle controls
$("#unitstatus-" + pid + "-text").toggle();
$("#unitstatus-" + pid + "-input").toggle();
return false;
}
function saveAddressStatusControl(aid) {
if(!Number.isInteger(aid) || aid < 1) {
return false;
}
var value = $("#addressstatus-" + aid + "-input select").val();
$.post("<?=self::getUrl("AddressDB","Api")?>",
{
'do': "updateAddressStatus",
id: aid,
status_id: value
},
function(success) {
if(success.status == "OK") {
var updates = success.result.updates;
//console.log(updates);
$("#addressstatus-" + updates.id + "-statustext").text(updates.status_code + " - " + updates.status_text);
$("#addressstatus-" + updates.id + "-text")
.addClass("text-success")
.data("status-id", updates.status_id);
setTimeout(() => {
$("#addressstatus-" + updates.id + "-text").removeClass("text-success")
}, 1500);
if("units" in updates && updates.units.length) {
updates.units.forEach(function (u) {
//console.log(u);
// update detail status text
/*// update list status text
$("#addressstatus-" + u.id + " .status").text(u.code + " - " + u.text);
$("#addressstatus-" + u.id + " .status").addClass("text-success");
setTimeout(() => { $("#preorder-" + u.id + " .status").removeClass("text-success") }, 1500);
*/
if (u.status_code) {
// update units
$("#unitstatus-" + u.id + "-statustext").text(u.status_code + " - " + u.status_text);
$("#unitstatus-" + u.id + "-text").addClass("text-success");
setTimeout(() => {
$("#unitstatus-" + u.id + "-text").removeClass("text-success")
}, 1500);
}
});
}
toggleAddressStatusControl(aid);
}
},
'json');
}
function saveUnitStatusControl(aid) {
if(!Number.isInteger(aid) || aid < 1) {
return false;
}
var value = $("#unitstatus-" + aid + "-input select").val();
$.post("<?=self::getUrl("AddressDB","Api")?>",
{
'do': "updateUnitStatus",
id: aid,
status_id: value
},
function(success) {
if(success.status == "OK") {
var updates = success.result.updates;
//console.log(updates);
/*$("#unitstatus-" + updates.id + "-statustext")
.text(updates.status_code + " - " + updates.status_text)
.addClass("text-success")
$("#unitstatus-" + updates.id + "-text").data("status-id", updates.status_id);
setTimeout(() => {
$("#unitstatus-" + updates.id + "-text").removeClass("text-success")
}, 1500);
*/
//console.log(updates.units.length);
if("units" in updates && updates.units.length) {
updates.units.forEach(function (u) {
//console.log(u);
// update detail status text
/*// update list status text
$("#unitstatus-" + u.id + " .status").text(u.code + " - " + u.text);
$("#unitstatus-" + u.id + " .status").addClass("text-success");
setTimeout(() => { $("#preorder-" + u.id + " .status").removeClass("text-success") }, 1500);
*/
//console.log(u.status_code);
//console.log((u.status_code));
if(u.status_code) {
// update units
$("#unitstatus-" + u.id + "-statustext").text(u.status_code + " - " + u.status_text);
$("#unitstatus-" + u.id + "-text").data("status-id", updates.status_id);
$("#unit-" + u.id + "-status").addClass("text-success");
setTimeout(() => {
$("#unit-" + u.id + "-status").removeClass("text-success")
}, 1500);
}
});
}
toggleUnitStatusControl(aid);
}
},
'json');
}
</script>
<?php include(realpath(dirname(__FILE__)."/../../$mfLayoutPackage")."/footer.php"); ?>

View File

@@ -35,6 +35,8 @@ class ADBHausnummer extends mfBaseModel {
$this->getGpsCoords();
}
$this->logChanges();
// Statuschange from Rimo statuschange for all units
foreach(ADBWohneinheitModel::search(["hausnummer_id" => $this->id]) as $wohneinheit) {
@@ -42,6 +44,34 @@ class ADBHausnummer extends mfBaseModel {
}
}
public function resetSaveNesting() {
mfValuecache::singleton()->delete("adbhausnummer-save-nesting-level-" . $this->id);
}
private function logChanges() {
$changes = $this->getChangedFields();
if(!count($changes)) return true;
$logstr = "";
foreach($changes as $key) {
if($key == "status_id") {
$old_status = new ADBStatus($this->_old_data->status_id);
$new_status = new ADBStatus($this->data->status_id);
$logstr .= "| '$key' => FROM '".$this->_old_data->$key."' TO '".$this->data->$key."' [".$old_status->code." => ".$new_status->code."]";
} else {
$logstr .= "| '$key' => FROM '".$this->_old_data->$key."' TO '".$this->data->$key."'";
}
}
$me = new User();
$me->loadMe();
$this->log->info(__CLASS__." Changes: User ".$me->username." $logstr");
return true;
}
public function getBuildingType() {

View File

@@ -0,0 +1,195 @@
<?php
class ADBRimoFcp extends mfBaseModel {
protected function init() {
$this->db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$this->table = "RimoFcp";
}
public function getProperty($name) {
if($this->$name == null) {
$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;
}
/********************************
* Begin static Model functions
*/
public static function create(Array $data) {
$model = new ADBRimoFcp();
$table_fields = [
"netzgebiet_id", "name", "rimo_id", "label", "building_type", "rimo_ex_state", "rimo_op_state", "gps_lat", "gps_long",
"create","edit"
];
foreach($data as $field => $value) {
if(in_array($field, $table_fields)) {
$model->$field = $value;
}
}
return $model;
}
public static function getFirst($filter) {
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$where = self::getSqlFilter($filter);
$sql = "SELECT RimoFcp.* FROM RimoFcp
WHERE $where
ORDER BY name
LIMIT 1";
mfLoghandler::singleton()->debug($sql);
$res = $db->query($sql);
if($db->num_rows($res)) {
$data = $db->fetch_object($res);
$item = new ADBRimoFcp($data);
if($item->id) {
return $item;
} else {
return null;
}
}
return null;
}
public static function getAll() {
$items = [];
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
$res = $db->select("RimoFcp", "*", "1=1 ORDER BY name");
if($db->num_rows($res)) {
while($data = $db->fetch_object($res)) {
$items[] = new ADBRimoFcp($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 RimoFcp
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 RimoFcp.* FROM RimoFcp
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 ADBRimoFcp($data);
}
}
return $items;
}
private static function getSqlFilter($filter) {
$where = "1=1 ";
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
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).")";
} elseif($netzgebiet_id === null) {
$where .= " AND netzgebiet_id IS NULL";
}
}
if(array_key_exists("name", $filter)) {
$name = $db->escape($filter['name']);
if($name) {
$where .= " AND RimoFcp.name='$name'";
}
}
if(array_key_exists("label", $filter)) {
$label = $db->escape($filter['label']);
if($label) {
$where .= " AND RimoFcp.label='$label'";
}
}
if(array_key_exists("building_type", $filter)) {
$building_type = $db->escape($filter['building_type']);
if($building_type) {
$where .= " AND RimoFcp.building_type='$building_type'";
}
}
if(array_key_exists("rimo_ex_state", $filter)) {
$rimo_ex_state = $db->escape($filter['rimo_ex_state']);
if($rimo_ex_state) {
$where .= " AND RimoFcp.rimo_ex_state='$rimo_ex_state'";
}
}
if(array_key_exists("rimo_op_state", $filter)) {
$rimo_op_state = $db->escape($filter['rimo_op_state']);
if($rimo_op_state) {
$where .= " AND RimoFcp.rimo_op_state='$rimo_op_state'";
}
}
if(array_key_exists("rimo_id", $filter)) {
$rimo_id = $db->escape($filter['rimo_id']);
if($rimo_id) {
$where .= " AND RimoFcp.rimo_id='$rimo_id'";
}
}
//var_dump($filter, $where);exit;
return $where;
}
}

View File

@@ -120,6 +120,7 @@ class ADBStatusModel {
$where = "1=1 ";
//var_dump($filter);exit;
$db = FronkDB::singleton(ADDRESSDB_DBHOST, ADDRESSDB_DBUSER, ADDRESSDB_DBPASS, ADDRESSDB_DBNAME);
if(array_key_exists("code", $filter)) {
$code = $filter['code'];
@@ -127,6 +128,20 @@ class ADBStatusModel {
$where .= " AND code=$code";
}
}
if(array_key_exists("type", $filter)) {
$type = $db->escape($filter['type']);
if($type) {
$where .= " AND type='$type'";
}
}
if(array_key_exists("!type", $filter)) {
$type = $db->escape($filter['!type']);
if($type) {
$where .= " AND (type IS NULL OR NOT type='$type')";
}
}
//var_dump($filter, $where);exit;

View File

@@ -30,6 +30,7 @@ class ADBWohneinheit extends mfBaseModel {
return true;
}
$this->logChanges();
// Statuschange from Rimo statuschange
AddressDB::handleRimoStatusUpdate($this->id);
@@ -77,6 +78,34 @@ class ADBWohneinheit extends mfBaseModel {
}
public function resetSaveNesting() {
mfValuecache::singleton()->delete("adbwohneinheit-save-nesting-level-" . $this->id);
}
private function logChanges() {
$changes = $this->getChangedFields();
if(!count($changes)) return true;
$logstr = "";
foreach($changes as $key) {
if($key == "status_id") {
$old_status = new ADBStatus($this->_old_data->status_id);
$new_status = new ADBStatus($this->data->status_id);
$logstr .= "| '$key' => FROM '".$this->_old_data->$key."' TO '".$this->data->$key."' [".$old_status->code." => ".$new_status->code."]";
} else {
$logstr .= "| '$key' => FROM '".$this->_old_data->$key."' TO '".$this->data->$key."'";
}
}
$me = new User();
$me->loadMe();
$this->log->info(__CLASS__." Changes: User ".$me->username." $logstr");
return true;
}
public function setNewStatusCode($new_status_code) {
if(!$new_status_code) return false;

View File

@@ -742,6 +742,12 @@ class AddressDBController extends mfBaseController {
case "findAddress":
$return = $this->findAddressApi();
break;
case "updateAddressStatus":
$return = $this->updateAddressStatusApi();
break;
case "updateUnitStatus":
$return = $this->updateUnitStatusApi();
break;
case "getFilteredBuildings":
$return = $this->getFilteredBuildingsApi();
break;
@@ -783,7 +789,117 @@ class AddressDBController extends mfBaseController {
$data['result'] = $return;
$this->returnJson($data);
}
private function updateAddressStatusApi() {
$address_id = $this->request->id;
if(!is_numeric($address_id) || $address_id < 1) {
return ["error" => 1];
return false;
}
$address = new ADBHausnummer($address_id);
if(!$address->id) {
return ["error" => 2];
return false;
}
$status_id = $this->request->status_id;
if(!is_numeric($status_id) || $status_id < 1) {
return ["error" => 3];
return false;
}
$status = new ADBStatus($status_id);
if(!$status->id) {
return ["error" => 4];
return false;
}
$address->status_id = $status_id;
$address->save();
$update = [
"id" => $address_id,
"status_id" => $status_id,
"status_code" => $status->code,
"status_text" => $status->name,
"units" => []
];
foreach(ADBWohneinheitModel::search(["hausnummer_id" => $address->id]) as $affected_unit) {
$up = [
"id" => $affected_unit->id,
"status_id" => $affected_unit->status_id,
"status_code" => $affected_unit->status->code,
"status_text" => $affected_unit->status->name,
];
$update["units"][] = $up;
}
return ["message" => "Status saved successfully", "id" => $address_id, "updates" => $update];
}
private function updateUnitStatusApi() {
$unit_id = $this->request->id;
if(!is_numeric($unit_id) || $unit_id < 1) {
return ["error" => 1];
return false;
}
$unit = new ADBWohneinheit($unit_id);
if(!$unit->id) {
return ["error" => 2];
return false;
}
$status_id = $this->request->status_id;
if(!is_numeric($status_id) || $status_id < 1) {
return ["error" => 3];
return false;
}
$status = new ADBStatus($status_id);
if(!$status->id) {
return ["error" => 4];
return false;
}
$linkes_units = [];
foreach(ADBWohneinheitModel::search(["hausnummer_id" => $unit->hausnummer_id]) as $lu) {
$linkes_units[$lu->id] = $lu->status_id;
}
$unit->status_id = $status_id;
$unit->save();
$update = [
"id" => $unit_id,
"status_id" => $status_id,
"status_code" => $status->code,
"status_text" => $status->name,
"units" => []
];
foreach(ADBWohneinheitModel::search(["hausnummer_id" => $unit->hausnummer_id]) as $affected_unit) {
if(!array_key_exists($affected_unit->id, $linkes_units)) continue;
if($linkes_units[$affected_unit->id] == $affected_unit->status_id) continue;
$up = [
"id" => $affected_unit->id,
"status_id" => $affected_unit->status_id,
"status_code" => $affected_unit->status->code,
"status_text" => $affected_unit->status->name,
];
$update["units"][] = $up;
}
return ["message" => "Status saved successfully", "id" => $unit_id, "updates" => $update];
}
private function getUnitApi() {
$id = $this->request->id;
if(!$id) return false;

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
use Phinx\Migration\AbstractMigration;
final class AdbStatusAddType extends AbstractMigration
{
public function up(): void
{
if($this->getEnvironment() == "thetool") {
}
if($this->getEnvironment() == "addressdb") {
$table = $this->table("Status");
$table->addColumn("type", "enum", ["null" => true, "default" => null, "values" => "hausnummer,wohneinheit", "after" => "name"]);
$table->update();
}
}
public function down(): void
{
if($this->getEnvironment() == "thetool") {
}
if($this->getEnvironment() == "addressdb") {
$this->table("Status")->removeColumn("type")->update();
}
}
}