Added general history in Preorder

This commit is contained in:
Frank Schubert
2024-07-18 14:28:41 +02:00
parent 578e813727
commit f08111c9a4
5 changed files with 415 additions and 305 deletions

View File

@@ -8,10 +8,10 @@
<li class="nav-item"><a class="nav-link active" href="#preorder-detail-<?=$preorder->id?>-detail" data-toggle="tab" aria-expanded="false">Details</a></li>
<li class="nav-item"><a class="nav-link" href="#preorder-detail-<?=$preorder->id?>-address" data-toggle="tab" aria-expanded="false">Adressdetails</a></li>
<li class="nav-item"><a class="nav-link" href="#preorder-detail-<?=$preorder->id?>-rimo" data-toggle="tab" aria-expanded="false">RIMO</a></li>
<li class="nav-item"><a class="nav-link" href="#preorder-detail-<?=$preorder->id?>-history" data-toggle="tab" aria-expanded="false">Status-Historie</a></li>
<?php if($me->is("Admin") && $preorder->adb_hausnummer->borderpoint_lat && $preorder->adb_hausnummer->borderpoint_long): ?>
<li class="nav-item"><a class="nav-link" href="#preorder-detail-<?=$preorder->id?>-map" data-toggle="tab" aria-expanded="false" onclick="loadBorderpointMap(<?=$preorder->id?>)">Übergabepunkt</a></li>
<?php endif; ?>
<li class="nav-item"><a class="nav-link" href="#preorder-detail-<?=$preorder->id?>-history" data-toggle="tab" aria-expanded="false">History</a></li>
</ul>
</div>
@@ -471,11 +471,11 @@
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="card-header bg-info text-white pl-2 pr-2 pt-1 pb-1">Addressdetails</div>
<div class="card-header bg-info text-white pl-2 pr-2 pt-1 pb-1">History</div>
<div class="row">
<div class="col-12">
<h3>Status-Historie</h3>
<h3>Status Historie</h3>
<table class="table table-sm table-striped">
<tr>
<th>Zeitpunkt</th>
@@ -484,7 +484,7 @@
<th>Neuer Status</th>
</tr>
<?php foreach($preorder->history as $history): ?>
<?php if($history->key != "preorderstatus_id") continue; ?>
<?php if($history->key != "status_id") continue; ?>
<tr>
<td><?=date("d.m.Y H:i:s", $history->create)?></td>
<td><?=$history->creator->name?></td>
@@ -493,6 +493,26 @@
</tr>
<?php endforeach; ?>
</table>
<h3>Gesamte Historie</h3>
<table class="table table-sm table-striped">
<tr>
<th>Zeitpunkt</th>
<th>Benutzer</th>
<th>Feld</th>
<th>Alter Wert</th>
<th>Neuer Wert</th>
</tr>
<?php foreach($preorder->history as $history): ?>
<tr>
<td><?=date("d.m.Y H:i:s", $history->create)?></td>
<td><?=$history->creator->name?></td>
<td><?=$history->key?></td>
<td><?=$history->getText("old")?></td>
<td><?=$history->getText("new")?></td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
</div>

View File

@@ -39,6 +39,7 @@ class Preorder extends mfBaseModel {
$this->creator = null;
$this->editor = null;
// prevent potential infinite loop
$nesting_level = mfValuecache::singleton()->get("preorder-save-nesting-level-".$this->id);
if(!$nesting_level) {
$nesting_level = 1;
@@ -51,9 +52,6 @@ class Preorder extends mfBaseModel {
return true;
}
// prevent potential infinite loop
//if($this->in_after_save) return true;
//$this->in_after_save++;
// update preorder OAID if it's different from the unit OAID
// but only if the unit OAID is of the same origin as the campaign
$old_oaid = $this->oaid;
@@ -64,10 +62,9 @@ class Preorder extends mfBaseModel {
}
//TODO: history start
if($this->status_id != $this->_old_data->status_id) {
//if($this->status_id != $this->_old_data->status_id) {
$this->createHistoryEntry();
$this->_old_data->status_id = $this->status_id;
}
//}
// run triggers based on new status
$this->runStatusTrigger();
@@ -79,13 +76,22 @@ class Preorder extends mfBaseModel {
}
public function createHistoryEntry() {
$history = PreorderHistoryModel::create([
"preorder_id" => $this->id,
"key" => 'preorderstatus_id',
"old_value" => $this->_old_data->status_id,
"new_value" => $this->status_id
]);
$history->save();
if(!$this->id) return true;
$changed = $this->getChangedFields();
foreach($changed as $field) {
$this->log->debug(__METHOD__.": $field changed from '".$this->_old_data->$field."' to '".$this->data->$field."'");
$history = PreorderHistoryModel::create([
"preorder_id" => $this->id,
"key" => $field,
"old_value" => $this->_old_data->$field,
"new_value" => $this->data->$field
]);
$history->save();
}
}
public function runStatusTrigger() {

View File

@@ -1,6 +1,7 @@
<?php
class PreorderHistory extends mfBaseModel {
protected $forcestr = ["old_value", "new_value"];
private $preorder;
private $creator;
private $editor;
@@ -25,14 +26,54 @@ class PreorderHistory extends mfBaseModel {
if(preg_match('/(.+)_id/', $this->key, $m)) {
if(array_key_exists(1, $m)) {
$object = ucfirst($m[1]);
$value = new $object($value);
if(!$value->id) return null;
if($object == "Status") $object = "Preorderstatus";
if($object == "Partner") $object = "Address";
if($object == "Adb_hausnummer") $object = "ADBHausnummer";
if($object == "Adb_wohneinheit") $object = "ADBWohneinheit";
if(class_exists($object)) {
$value = new $object($value);
if(!$value->id) return null;
}
}
}
return $value;
}
public function getText($type = "new") {
$value = $this->getValue($type);
if($value === null) return "";
if($this->key == "attributes") {
$attribs = "";
$jdec = json_decode($value);
if(is_object($jdec)) {
foreach(get_object_vars($jdec) as $k => $v) {
$attribs .= "$k: $v<br />";
}
return $attribs;
}
}
if(!is_object($value)) {
return $value;
}
if(get_class($value) == "Preorderstatus") {
return $value->code." - ".$value->name;
}
if(get_class($value) == "Address") {
return $value->getCompanyOrName();
}
if(get_class($value) == "ADBHausnummer") {
return $value->getAddress();
}
if(get_class($value) == "ADBWohneinheit") {
return $value->id." - ".(string)$value;
}
if(get_class($value) == "Preordercampaign") {
return $value->name;
}
}
public function getProperty($name) {

View File

@@ -41,7 +41,7 @@ class PreorderHistoryModel {
$db = FronkDB::singleton();
$where = self::getSqlFilter($filter);
$res = $db->select("PreorderHistory", "*", "$where ORDER BY preorder_id,`key`,`create` LIMIT 1");
$res = $db->select("PreorderHistory", "*", "$where ORDER BY `create`,`key` LIMIT 1");
if ($db->num_rows($res)) {
$data = $db->fetch_object($res);
$item = new PreorderHistory($data);
@@ -59,7 +59,7 @@ class PreorderHistoryModel {
$db = FronkDB::singleton();
$res = $db->select("PreorderHistory", "*", "1=1 ORDER BY preorder_id,`key`,`create`");
$res = $db->select("PreorderHistory", "*", "1=1 ORDER BY `create`,`key`");
if ($db->num_rows($res)) {
while ($data = $db->fetch_object($res)) {
$items[] = new PreorderHistory($data);
@@ -91,7 +91,7 @@ class PreorderHistoryModel {
$where = self::getSqlFilter($filter);
$sql = "SELECT * FROM PreorderHistory
WHERE $where
ORDER BY preorder_id,`key`,`create`";
ORDER BY `create`,`key`";
mfLoghandler::singleton()->debug($sql);
if (is_array($limit) && count($limit)) {

View File

@@ -4,314 +4,357 @@
* Does most of the dirty work in getting Database entries into
* an object.
* Takes an ID, or FronkDB table row for automatic loading
* @author fronk
* @param optional ID or table row $_
* @author fronk
*/
if(!defined("FRONKDB")) {
define("FRONKDB", true);
define("FRONKDB", true);
}
class mfBaseModel {
public $id;
public $data;
public $_old_data;
protected $create;
protected $edit;
private $worker;
protected $forcestr;
public $id;
public $data;
public $_old_data;
protected $create;
protected $edit;
private $worker;
protected $forcestr;
protected $mode = "new";
protected $saved = 0;
protected $db;
protected $log;
protected $table=false;
protected $fieldprefix=false;
protected $mode = "new";
protected $saved = 0;
protected $db;
protected $log;
protected $table = false;
protected $fieldprefix = false;
/**
* Takes ID or DB row as arguments
* @param id or table row $_
*/
public function __construct($_=NULL) {
$this->log=mfLoghandler::singleton();
$this->table=get_class($this);
$this->data = new stdClass();
$this->_old_data = new stdClass();
/**
* Takes ID or DB row as arguments
* @param id or table row $_
*/
public function __construct($_ = NULL) {
$this->log = mfLoghandler::singleton();
$this->table = get_class($this);
$this->data = new stdClass();
$this->_old_data = new stdClass();
if(defined("MFMODEL_USEFIELDPREFIX") && MFMODEL_USEFIELDPREFIX==true) {
$this->prefixfields=true;
}
$this->data = new stdClass();
if(FRONKDB) {
$this->db=FronkDB::singleton();
}
if(method_exists($this, "init")) {
$this->init($_);
}
if(is_numeric($_)) {
$this->fetch($_);
} elseif(is_object($_)) {
$this->load($_);
}
}
public function load($row) {
if(!is_object($this->data)) {
$this->data = new stdClass();
}
foreach($row as $field => $value) {
if($this->fieldprefix) {
if(preg_match('/^'.$this->fieldprefix.'_(.+)$/',$field,$m)) {
$field=$m[1];
}
}
if($field=="id"
|| $field=="create"
|| $field=="edit") continue;
$this->data->$field=$value;
}
$this->id=$row->id;
if(!property_exists($row, "create")) {
$row->create = date("U");
}
if(!property_exists($row, "edit")) {
$row->edit = date("U");
}
$this->create=$row->create;
$this->edit=$row->edit;
if($this->fieldprefix) {
$prop=$this->fieldprefix."_id";
$this->id=$row->$prop;
}
$this->_old_data = clone($this->data);
$this->_old_data->id = $this->id;
$this->_old_data->create = $this->create;
$this->_old_data->edit = $this->edit;
$this->mode = "update";
if(method_exists($this, "afterLoad")) {
$this->afterLoad();
}
return true;
}
public function fetch($id) {
$where="id=$id";
if($this->fieldprefix) {
$where=$this->fieldprefix."_id=$id";
}
$res=$this->db->select($this->table,"*","$where");
if($this->db->num_rows($res)) {
$data=$this->db->fetch_object($res);
$this->load($data);
return true;
}
return false;
}
public function update(Array $data) {
foreach($data as $key => $value) {
if($value === null) {
$this->$key = null;
} else {
$this->$key = $value;
}
}
}
public function save() {
if(method_exists($this, "beforeSave")) {
$this->beforeSave();
}
$fields=$this->buildFields();
$forcestr = array();
if(!$this->fieldprefix && is_array($this->forcestr) && count($this->forcestr)) {
$forcestr = $this->forcestr;
}
if(is_array($this->forcestr) && count($this->forcestr)) {
foreach($this->forcestr as $fstr) {
$forcestr[] = $this->fieldprefix . "_$fstr";
}
}
if(!is_array($fields) or !count($fields)) {
return false;
}
if($this->id) {
$id=$this->id;
$where="`id`=$id";
if($this->fieldprefix) {
$where="`".$this->fieldprefix."_id`=$id";
}
if($this->db->update($this->table,$fields,$where,$forcestr)) {
$this->saved++;
if(method_exists($this, "afterSave")) {
$this->afterSave();
if(defined("MFMODEL_USEFIELDPREFIX") && MFMODEL_USEFIELDPREFIX == true) {
$this->prefixfields = true;
}
return $id;
}
} else {
if($this->db->insert($this->table,$fields,$forcestr)) {
$id=mysqli_insert_id($this->db->link);
$this->id=$id;
$this->saved++;
if(method_exists($this, "afterSave")) {
$this->afterSave();
$this->data = new stdClass();
if(FRONKDB) {
$this->db = FronkDB::singleton();
}
return $id;
}
}
return false;
}
protected function buildFields() {
$fields = array();
foreach($this->data as $field => $value) {
if($this->fieldprefix && !strstr($field,"_")) {
$field = $this->fieldprefix."_$field";
}
$fields[$field]=$value;
}
if(method_exists($this, "init")) {
$this->init($_);
}
if(!$this->create) {
$this->create = date('U');
}
$this->edit = date('U');
foreach(array("create","edit") as $f) {
$fields[$f] = $this->$f;
}
if(method_exists($this, "afterBuildFields")) {
$fields = $this->afterBuildFields($fields);
if(is_numeric($_)) {
$this->fetch($_);
} elseif(is_object($_)) {
$this->load($_);
}
}
return $fields;
}
public function delete() {
if($this->id) {
$id=$this->id;
$where="id=$id";
if($this->fieldprefix && !strstr($field,"_")) {
$where=$this->fieldprefix."_id=$id";
}
public function load($row) {
if(!is_object($this->data)) {
$this->data = new stdClass();
}
foreach($row as $field => $value) {
if($this->fieldprefix) {
if(preg_match('/^' . $this->fieldprefix . '_(.+)$/', $field, $m)) {
$field = $m[1];
}
}
if($field == "id"
|| $field == "create"
|| $field == "edit") continue;
$this->data->$field = $value;
}
$this->id = $row->id;
if(!property_exists($row, "create")) {
$row->create = date("U");
}
if(!property_exists($row, "edit")) {
$row->edit = date("U");
}
$this->create = $row->create;
$this->edit = $row->edit;
if($this->fieldprefix) {
$prop = $this->fieldprefix . "_id";
$this->id = $row->$prop;
}
$this->_old_data = clone($this->data);
$this->_old_data->id = $this->id;
$this->_old_data->create = $this->create;
$this->_old_data->edit = $this->edit;
$this->mode = "update";
if(method_exists($this, "afterLoad")) {
$this->afterLoad();
}
return true;
}
public function fetch($id) {
$where = "id=$id";
if($this->fieldprefix) {
$where = $this->fieldprefix . "_id=$id";
}
$res = $this->db->select($this->table, "*", "$where");
if($this->db->num_rows($res)) {
$data = $this->db->fetch_object($res);
$this->load($data);
return true;
}
return false;
}
public function update(array $data) {
foreach($data as $key => $value) {
if($value === null) {
$this->$key = null;
} else {
$this->$key = $value;
}
}
}
public function save() {
if(method_exists($this, "beforeSave")) {
$this->beforeSave();
}
$fields = $this->buildFields();
$forcestr = array();
if(!$this->fieldprefix && is_array($this->forcestr) && count($this->forcestr)) {
$forcestr = $this->forcestr;
}
if(is_array($this->forcestr) && count($this->forcestr)) {
foreach($this->forcestr as $fstr) {
$forcestr[] = $this->fieldprefix . "_$fstr";
}
}
if(!is_array($fields) or !count($fields)) {
return false;
}
if($this->id) {
$id = $this->id;
$where = "`id`=$id";
if($this->fieldprefix) {
$where = "`" . $this->fieldprefix . "_id`=$id";
}
if($this->db->update($this->table, $fields, $where, $forcestr)) {
$this->saved++;
if(method_exists($this, "afterSave")) {
$this->afterSave();
}
return $id;
}
} else {
if($this->db->insert($this->table, $fields, $forcestr)) {
$id = mysqli_insert_id($this->db->link);
$this->id = $id;
$this->saved++;
if(method_exists($this, "afterSave")) {
$this->afterSave();
}
return $id;
}
}
return false;
}
protected function buildFields() {
$fields = array();
foreach($this->data as $field => $value) {
if($this->fieldprefix && !strstr($field, "_")) {
$field = $this->fieldprefix . "_$field";
}
$fields[$field] = $value;
}
if(!$this->create) {
$this->create = date('U');
}
$this->edit = date('U');
foreach(array("create", "edit") as $f) {
$fields[$f] = $this->$f;
}
if(method_exists($this, "afterBuildFields")) {
$fields = $this->afterBuildFields($fields);
}
return $fields;
}
public function delete() {
if($this->id) {
$id = $this->id;
$where = "id=$id";
if($this->fieldprefix && !strstr($field, "_")) {
$where = $this->fieldprefix . "_id=$id";
}
if(method_exists($this, "beforeDelete")) {
// delete can be canceled
if(!$this->beforeDelete()) {
return false;
}
}
if($this->db->delete($this->table,$where)) {
if(method_exists($this, "afterDelete")) {
$this->afterDelete();
if($this->db->delete($this->table, $where)) {
if(method_exists($this, "afterDelete")) {
$this->afterDelete();
}
$this->data = new stdClass();
$this->id = "";
return true;
}
}
$this->data=new stdClass();
$this->id="";
return true;
}
}
return false;
}
public function new() {
if($this->mode == "new" && $this->saved <= 1) {
return "new";
} else {
return "update";
return false;
}
}
public function startTransaction() {
$this->db->query("START TRANSACTION");
}
public function commitTransaction() {
$this->db->query("COMMIT");
}
public function rollbackTransaction() {
$this->db->query("ROLLBACK");
}
// generic functions for entity-classes
public function toArray() {
if(!$this->id) {
return [];
}
$item = [];
$item['id'] = $this->id;
foreach($this->data as $key => $value) {
$item[$key] = $value;
}
return $item;
}
public function __toString() {
return (string) $this->data->Name;
}
public function __get($name) {
if($name == "create" || $name == "edit") {
if(isset($this->data->$name)) {
return $this->data->$name;
} else {
return $this->$name;
}
}
if(isset($this->data->$name)) {
return $this->data->$name;
} elseif(property_exists($this, $name)) {
if(method_exists($this, "getProperty")) {
$prop = $this->getProperty($name);
if($prop === null){
return null;
protected function getChangedFields($include_system = false) {
if(!$this->_old_data->id) return [];
if(!is_object($this->data) || !is_object($this->_old_data)) {
return [];
}
return $prop;
} else {
return $this->$name;
}
}
return null;
}
public function __set($name,$value) {
if($name=="create") {
$this->create=intval($value);
}
$this->data->$name=$value;
return true;
}
$changes = [];
public function __unset($name) {
unset($this->data->$name);
}
public function __debugInfo() {
$vars = get_object_vars($this);
if(is_object($vars['db'])) $vars['db'] = "object(FronkDB)";
if(is_object($vars['log'])) $vars['log'] = 'object(mfLoghandler)';
return $vars;
}
foreach($this->data as $field => $value) {
if(!$include_system && in_array($field, ["id", "create_by", "edit_by", "create", "edit"])) continue;
if(is_object($value)) continue;
if(!property_exists($this->_old_data, $field)) {
$changes[] = $field;
continue;
}
if($value != $this->_old_data->$field) {
$changes[] = $field;
}
}
foreach($this->_old_data as $field => $value) {
if(!$include_system && in_array($field, ["id", "create_by", "edit_by", "create", "edit"])) continue;
if(is_object($value)) continue;
if(in_array($field, $changes)) {
continue;
}
if(!property_exists($this->data, $field)) {
$changes[] = $field;
continue;
}
if($value != $this->data->$field) {
$changes[] = $field;
}
}
return $changes;
}
public function new() {
if($this->mode == "new" && $this->saved <= 1) {
return "new";
} else {
return "update";
}
}
public function startTransaction() {
$this->db->query("START TRANSACTION");
}
public function commitTransaction() {
$this->db->query("COMMIT");
}
public function rollbackTransaction() {
$this->db->query("ROLLBACK");
}
// generic functions for entity-classes
public function toArray() {
if(!$this->id) {
return [];
}
$item = [];
$item['id'] = $this->id;
foreach($this->data as $key => $value) {
$item[$key] = $value;
}
return $item;
}
public function __toString() {
return (string)$this->data->Name;
}
public function __get($name) {
if($name == "create" || $name == "edit") {
if(isset($this->data->$name)) {
return $this->data->$name;
} else {
return $this->$name;
}
}
if(isset($this->data->$name)) {
return $this->data->$name;
} elseif(property_exists($this, $name)) {
if(method_exists($this, "getProperty")) {
$prop = $this->getProperty($name);
if($prop === null) {
return null;
}
return $prop;
} else {
return $this->$name;
}
}
return null;
}
public function __set($name, $value) {
if($name == "create") {
$this->create = intval($value);
}
$this->data->$name = $value;
return true;
}
public function __unset($name) {
unset($this->data->$name);
}
public function __debugInfo() {
$vars = get_object_vars($this);
if(is_object($vars['db'])) $vars['db'] = "object(FronkDB)";
if(is_object($vars['log'])) $vars['log'] = 'object(mfLoghandler)';
return $vars;
}
}