redesign for mulituser

change validation concept (client and server)
using entities
This commit is contained in:
Markus
2026-10-06 08:55:35 +02:00
parent 14e050e4ba
commit 995e2ec111
41 changed files with 2402 additions and 1223 deletions

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace App\Models\Cast;
//namespace CodeIgniter\DataCaster\Cast;
use CodeIgniter\Database\BaseConnection;
use CodeIgniter\Exceptions\InvalidArgumentException;
use CodeIgniter\DataCaster\Cast\BaseCast;
use CodeIgniter\I18n\Time;
// The class must inherit the CodeIgniter\DataCaster\Cast\BaseCast class
class CastMyDate extends BaseCast
{
public static function get( mixed $value, array $params = [], ?object $helper = null,): string {
if (! is_string($value)) {
self::invalidTypeValueError($value);
}
if (! $helper instanceof BaseConnection) {
$message = 'The parameter $helper must be BaseConnection.';
throw new InvalidArgumentException($message);
}
$format = $helper->dateFormat['date'];
return Time::createFromFormat($format, $value)->toLocalizedString($params[0] ?? 'yyyy-MM-dd');
}
public static function set( mixed $value, array $params = [], ?object $helper = null,): string {
if ( is_string($value)) {
$value = Time::createFromFormat("Y-m-d", $value);
}
if (! $value instanceof Time) {
self::invalidTypeValueError($value);
}
if (! $helper instanceof BaseConnection) {
$message = 'The parameter $helper must be BaseConnection.';
throw new InvalidArgumentException($message);
}
$format = $helper->dateFormat['date'];
return $value->format($format);
}
}

View File

@@ -3,41 +3,65 @@
use CodeIgniter\Model;
class mAccounts extends Model {
protected $table = 'budget_accounts';
private $defaultTableName='_budget_accounts';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'object';
protected $useSoftDeletes = false;
protected $useSoftDeletes = true;
protected $deletedField ="deleted_at";
protected $allowedFields = ['parent_id','type','bookable','description','lkz'];
protected $allowedFields = ['parent_id','bookable','description','account','monitor','deleted_at'];
protected $useTimestamps = false;
private $mAccountList = array();
private ?array $mAccountList = null;
protected function initialize()
{
$result = $this->findAll();
foreach ($result as $value) {
$this->mAccountList[$value->id] = $value;
protected array $casts = [
'bookable' => 'boolean',
'monitor' => 'boolean',
'account' => 'boolean',
];
protected function initialize() {
log_message('debug','mAccounts initialize');
$this->table = auth()->user()->preFixDB.$this->defaultTableName;
$this->checkOrCreateTable();
}
/**
* Sicherstellen dass mAccountList gefüllt ist
*/
private function populateAccountList(): void {
if ($this->mAccountList === null) {
log_message('debug','mAccounts populateAccountList New');
$result = $this->withDeleted()->findAll();
// log_message('debug','mAccounts DB-Result '.json_encode($result));
$this->mAccountList = [];
foreach ($result as $value) {
$this->mAccountList[$value->id] = $value;
}
//log_message('debug','mAccounts intern List '.json_encode($this->mAccountList));
}
}
/**
* Erstellt DropDownListe aus gegeben array
* @param array liste der daten
* @param bool wenn true wird auch ein 0-Eintrag erstellt
* @param array $data liste der daten
* @param bool $withnull wenn true wird auch ein 0-Eintrag erstellt
* @param int $key index für null eintrag
* @return mixed
*/
private function createDropDownList($data,$withnull = true,$key=0)
{
private function createDropDownList(array $data, bool $withnull = true, int $key=0) {
$liste = array();
if ($withnull)
$liste[$key] = '-----';
foreach ( $data as $row )
{
if ($withnull){
if ($key > 0)
$liste[$key] = '-----';
// else
// $liste[""] = '-----';
}
foreach ( $data as $row ) {
$liste[$row->id] = $row->description;
}
asort( $liste );
@@ -46,114 +70,114 @@ class mAccounts extends Model {
/**
* holt Text vom gegebenen Element
* @param int id des gewünschten Elements
* @param int $id ID des gewünschten Elements
* @return string Full Name of Entry
*/
public function getDropDownEntry($id){
public function getDropDownEntry(int $id) {
$this->populateAccountList();
$element = $this->mAccountList[$id];
$description = $element->description;
$id = $element->parent_id;
while ( $id > 0 )
{
while ( $id > 0 ) {
$description = $this->mAccountList[$id]->description .'-'.$description;
$id = $this->mAccountList[$id]->parent_id;
}
return $description;;
return $description;
}
private function filterIt(string $type = 'all', bool $bookableOnly = true, bool $withDeleted = false, ?int $defaultKey = null){
return unserialize(serialize(array_filter($this->mAccountList, function($var) use($type, $bookableOnly, $withDeleted, $defaultKey) {
if ($defaultKey !== null && $var->id == $defaultKey)
return true;
if (!($withDeleted) && $var->deleted_at)
return false;
if ($bookableOnly && !$var->bookable)
return false;
if ($type == 'Acc' && !$var->account)
return false;
elseif ($type == 'InOut' && $var->account)
return false;
return true;
})));
}
/**
* liefert DropDown Liste mit gegeben Suchparametern
* @param string Kontotyp "InOut,In,Out,Acc"
* @param bool ob bookable gesetzt sein muss
* @return bool ob lkz Flag gesetzt sein darf
* @param string $type Kontotyp "InOut,Acc,all"
* @param bool $bookableOnly ob bookable gesetzt sein muss
* @param bool $withDeleted ob gelöschte auch
* @return array fertige DropDownListe
*/
public function getDropDownList($type, $bookable = true, $lkz = false )
{
if ($bookable == true)
$this->where('bookable',true);
if ($lkz == false) $this->where('lkz',NULL);
if ( $type == 'InOut' ) $this->where('type !=','account');
elseif ( $type == 'Acc' ) $this->where('type','account');
elseif ( $type == 'In' ) $this->where('type','input');
elseif ( $type == 'Out' ) $this->where('type','output');
$this->orderBy('description');
$result = $this->findAll();
$parent = array();
foreach ( $result as &$element )
{
public function getDropDownList(string $type, bool $bookableOnly = true, bool $withDeleted = false, ?int $defaultKey = null) : array {
$this->populateAccountList();
$result = $this->filterIt($type,$bookableOnly,$withDeleted,$defaultKey);
foreach ( $result as &$element ) {
$id = $element->parent_id;
while ( $id > 0 )
{
while ( $id > 0 ) {
$element->description = $this->mAccountList[$id]->description .'-'.$element->description;
if ($this->mAccountList[$id]->parent_id == 0){
$parent[] = (object)['id' => $element->id,'description' => $element->description ];
}
$id = $this->mAccountList[$id]->parent_id;
}
}
return $this->createDropDownList($result);
}
/**
public function getCurDDLists(string $type, bool $bookableOnly = true, bool $withDeleted = false, ?int $defaultKey = null ) : array {
$this->populateAccountList();
$list = $this->filterIt($type,$bookableOnly,$withDeleted, $defaultKey);
$parent = $this->getParent($defaultKey);
}
/**
* liefert 2 DropDown Listen mit gegeben Suchparametern
* parent für Vorselektion, subs für Untereinträge
* @param string Kontotyp "InOut,In,Out,Acc"
* @param bool ob bookable gesetzt sein muss
* @return bool ob lkz Flag gesetzt sein darf
* @param string $type Kontotyp "InOut,In,Out,Acc"
* @param bool $bookableOnly ob bookable gesetzt sein muss
* @param bool $withDeleted ob lkz Flag gesetzt sein darf
* @return array fertige DropDownListen mit parent und subs
*/
public function getDropDownLists($type, $bookable = true, $lkz = false )
{
if ($bookable == true) $this->where('bookable',true);
if ($lkz == false) $this->where('lkz',null);
if ( $type == 'InOut' ) $this->where('type !=','account');
elseif ( $type == 'Acc' ) $this->where('type','account');
elseif ( $type == 'In' ) $this->where('type','output');
elseif ( $type == 'Out' ) $this->where('type','input');
$this->orderBy('description');
$result = $this->findAll();
public function getDropDownLists(string $type, bool $bookableOnly = true, bool $withDeleted = false, ?int $defaultKey = null ) : array {
$this->populateAccountList();
$list = $this->filterIt($type,$bookableOnly,$withDeleted, $defaultKey);
$parent = array();
$listen = array();
foreach ( $result as &$element )
{
foreach ( $list as &$element ) {
$id = $element->parent_id;
while ( $id > 0 )
{
if ($this->mAccountList[$id]->lkz == 1) continue 2;
while ( $id > 0 ) {
if ($this->mAccountList[$id]->deleted_at) continue 2;
if ($this->mAccountList[$id]->parent_id == 0){
if (!array_key_exists($id, $parent))
$parent[$id] = (object)['id' => $id,'description' => $this->mAccountList[$id]->description ];
$listen[$id][$element->id] = (object)['id' => $element->id,'description' => $element->description ];
}
else{
} else{
$element->description = $this->mAccountList[$id]->description .'-'.$element->description;
}
$id = $this->mAccountList[$id]->parent_id;
}
}
$subs = array();
$subs[0] = $this->createDropDownList(array());
$subs[0] = ["0"=>"----"];
foreach ( $listen as $key => $element ){
$subs[$key] = $this->createDropDownList($element,($this->mAccountList[$key]->bookable=="t"), $key);
$subs[$key] = $this->createDropDownList($element,($this->mAccountList[$key]->bookable), $key);
}
return array('parent'=> $this->createDropDownList($parent),'subs'=>(object)$subs);
}
/**
* liefert parent id für category
* @param int account id
* @param int $sid account id
* @return int parent id
*/
public function getParent($sid){
public function getParent(int $sid): int{
if ($sid == 0) return 0;
$result = $sid;
$id = $this->mAccountList[$sid]->parent_id;
while ( $id > 0 )
{
$result = $id;
$id = $this->mAccountList[$id]->parent_id;
$this->populateAccountList();
while ( $this->mAccountList[$sid]->parent_id > 0 ) {
$sid = $this->mAccountList[$sid]->parent_id;
}
return $result;
return $sid;
}
@@ -163,45 +187,71 @@ class mAccounts extends Model {
*/
public function getTreeData(){
helper('array');
$parents = array();
$subs = array();
foreach ( $this->mAccountList as $element )
{
if ($element->parent_id == 0)
$parents[$element->id] = $element;
}
foreach ( $this->mAccountList as $element )
{
// if ($element->parent_id > 0)
// echo "".$parents[$element->parent_id]->id;
$this->populateAccountList();
$parents = array_filter($this->mAccountList, function($var) {
return ($var->parent_id == 0);
});
foreach ( $this->mAccountList as $element ) {
if (($element->parent_id > 0) && array_key_exists($element->parent_id , $parents))
$parents[$element->parent_id]->subs[$element->id] = $element;
}
array_sort_by_multiple_keys($parents, ['description' => SORT_ASC]);
return ['parents'=>$parents,'subs'=>$subs, 'all'=>$this->mAccountList];
return ['parents'=>$parents, 'all'=>$this->mAccountList];
}
/**
/**
* erstellt oder updatet den gegeben Account
* @var array formulardaten
*/
public function saveAccount($data){
public function saveAccount(array $data) : bool{
$this->set('parent_id',$data['parent']);
$this->set('type', $data['type']);
$this->set('bookable', array_key_exists('bookable', $data) ? true : false);
$this->set('bookable', array_key_exists('bookable', $data));
$this->set('monitor', array_key_exists('monitor', $data));
$this->set('account', array_key_exists('account', $data));
$this->set('description', $data['description']);
$this->set('lkz', (array_key_exists('lkz', $data) ? 1 : null));
$this->set('deleted_at', (array_key_exists('deleted_at', $data) ? 'LOCALTIMESTAMP' : null),(array_key_exists('deleted_at', $data)? false: true));
if ($data['id'] == 0)
$this->insert();
$result = $this->insert();
else
$this->update($data['id']);
$this->initialize();
$result = $this->update($data['id']);
log_message('debug',$this->db->getLastQuery());
return $result;
}
public function checkType($id, $type){
return ($this->mAccountList[$id]->type == $type);
/**
* prüft ob gegebene Kategorie ein Konot ist
*
* @param int $id
* @return bool
*/
public function isAccount(int $id){
$this->populateAccountList();
return ($this->mAccountList[$id]->account);
}
public function checkOrCreateTable(){
log_message('debug',"Check or Create Account Table");
if ($this->db->tableExists($this->table)) return;
$forge = \Config\Database::forge();
$fields = array(
'id' => array( 'type' => 'serial'),
'parent_id' => array( 'type' => 'integer','default'=>'0'),
'bookable' => array( 'type' => 'boolean' ),
'description' => array( 'type' => 'character varying','constraint' => '80'),
'monitor' => array( 'type' => 'boolean','default'=>'false' ),
'account' => array( 'type' => 'boolean','default'=>'false' ),
'deleted_at'=> array( 'type' => 'timestamp without time zone','null'=>true),
);
$forge->addField( $fields );
$forge->addPrimaryKey('id');
// $this->db->query("CREATE TABLE $this->table (LIKE $this->defaultTableName INCLUDING DEFAULTS INCLUDING CONSTRAINTS) PARTITION BY RANGE (datum);");
$forge->createTable($this->table,true);
// CREATE TABLE temperatures_y2025q1 PARTITION OF temperatures
// FOR VALUES FROM ('2025-01-01') TO ('2025-04-01');
}
};
?>

View File

@@ -3,31 +3,60 @@
use CodeIgniter\Model;
class mBillDetails extends Model {
protected $table = 'budget_billdetails';
private $defaultTableName='_budget_billdetails';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'object';
protected $useSoftDeletes = false;
protected $returnType = \App\Entities\eBookingLine::class;
protected $useSoftDeletes = true;
protected $deletedField ="deleted_at";
protected $allowedFields = ['bill_id','comment','account_id','subamount','lkz'];
protected $allowedFields = ['bill_id','comment','account_id','subamount','deleted_at'];
protected $useTimestamps = false;
// public function getEntries($id){
// $this->select('mw_budget_bookingdetails.*,mw_budget_categories.description');
// $this->join('mw_budget_categories', 'mw_budget_categories.id = mw_budget_bookingdetails.account_id', 'left');
// $result = $this->orderBy('id','asc')->where('bill_id',$id)->findAll();
// foreach ($result as $key => $value) {
// // $value->datum = date( "d.m.Y", strtotime( $value->datum ));
// // $value->amount = number_format( $value->amount , 2, ',', '.' );
// }
// return $result;
// }
protected array $casts = [
'subamount' => 'float',
'account_id' => 'int',
'bill_id' => 'int',
];
public function getDetails($ids){
protected $validationRules = [
'bill_id' => 'required|numeric',
'account_id' => 'required|numeric',
];
protected $validationMessages = [
'bill_id' => [
'required' => 'Die Buchungsnummer muss angegeben sein.',
'numeric' => 'Die Buchungsnummer muss eine Zahl sein.',
],
'account_id' => [
'required' => 'Die Kategorie muss angegeben sein.',
'numeric' => 'Die Kategorie muss eine Zahl sein.',
],
];
protected function initialize() {
log_message('debug','mBillDetails initialize');
$this->table = auth()->user()->preFixDB.$this->defaultTableName;
$this->checkOrCreateTable();
}
public function getEntries(int $id){
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
$this->select($this->table.'.*,'.$accounts->getTable().'.description');
$this->join($accounts->getTable(), $accounts->getTable().'.id = '.$this->table.'.account_id', 'left');
$result = $this->orderBy('id','asc')->where('bill_id',$id)->findAll();
return $result;
}
/**
* liefert für gegebene Buchung Details
* @param array<int> $ids id der Buchung
*/
public function getDetails(array $ids): array {
$quelle = model('App\Models\mAccounts');
$rows = $this->whereIn('bill_id', $ids)->findAll();
$result = array();
@@ -37,9 +66,18 @@ class mBillDetails extends Model {
}
return $result;
}
public function getEntriesForForm($billId, &$result, $accounts){
$this->select('budget_billdetails.*,budget_accounts.description');
$this->join('budget_accounts', 'budget_accounts.id = budget_billdetails.account_id', 'left');
/**
* liefert für gegebene Buchung Details im Formularformat
* @param int $billId id der Buchung
* @param mixed $result Datenstruktur für Formular mit defaults
* @param \App\Models\mAccounts $accounts modelClass für Konten
*
*/
public function getEntriesForForm(int $billId, &$result){
$accounts = model('App\Models\mAccounts');
$this->select($this->table.'.*,'.$accounts->getTable().'.description');
$this->join($accounts->getTable(), $accounts->getTable().'.id = '.$this->table.'.account_id', 'left');
$data = $this->orderBy('id','asc')->where('bill_id',$billId)->findAll();
$amount = 0.0;
foreach ($data as $key => $row){
@@ -58,12 +96,12 @@ class mBillDetails extends Model {
$result['total_in']= ($amount >= 0.0)?number_format( abs( $amount ), 2, ',', '' ):'';
$result['total_out']= ($amount < 0.0)?number_format( abs( $amount ), 2, ',', '' ):'';
}
else if ($accounts->checkType($result['category'][0],'account'))
else if ($accounts->isAccount($result['category'][0]))
$result['transfer'] = true;
return $result;
}
public function saveEntries($data, $billId){
public function saveEntries(array $data, int $billId){
for ($i=0;$i<10;$i++){
if ($data['category'][$i] > 0){
$this->set('subamount', floatval($data['input'][$i])-floatval($data['output'][$i])); //floatval($data['total_in'])-floatval($data['total_out']));
@@ -82,5 +120,28 @@ class mBillDetails extends Model {
}
}
}
public function checkOrCreateTable(){
log_message('debug',"Check or Create BillDetails Table");
if ($this->db->tableExists($this->table)) return;
log_message('debug',"Create BillDetails Table ".$this->table);
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
$bills = model('App\Models\mBills'); /* @var \App\Models\mBills $bills */
$forge = \Config\Database::forge();
$fields = array(
'id' => array( 'type' => 'serial'),
'bill_id' => array( 'type' => 'integer'),
'account_id' => array( 'type' => 'integer' ),
'subamount' => array( 'type' => 'numeric','constraint' => '9,2' ),
'comment' => array( 'type' => 'character varying','constraint' => '150'),
'deleted_at'=> array( 'type' => 'timestamp without time zone','null'=>true),
);
$forge->addField( $fields );
$forge->addPrimaryKey('id');
$forge->addForeignKey('bill_id', $bills->getTable(), 'id','NO ACTION','NO ACTION','bill_id_fk');
$forge->addForeignKey('account_id', $accounts->getTable(), 'id','NO ACTION','NO ACTION','account_id_fk');
$forge->createTable($this->table,true);
log_message('debug','Create BillDetails Table '.$this->db->lastQuery);
}
};
?>

View File

@@ -1,33 +1,58 @@
<?php namespace App\Models;
use App\Models\Cast\CastMyDate;
use CodeIgniter\Model;
use App\Models\Mbookingdetails;
use App\Models\Mcategories;
class mBills extends Model {
protected $table = 'budget_bills';
private $defaultTableName='_budget_bills';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'object';
protected $returnType = \App\Entities\eBooking::class;
protected $useSoftDeletes = true;
protected $deletedField ="deleted_at";
protected $useSoftDeletes = false;
//TODO timestamps aktivieren
// protected $createdField = 'created_at';
// protected $updatedField = 'updated_at';
// protected $deletedField = 'deleted_at';
protected $allowedFields = ['renummer','datum','receiver','source_id','amount','type','comment','validate','lkz','rechnung'];
protected $allowedFields = ['datum','receiver','source_id','amount','validate','deleted_at','rechnung'];
protected $useTimestamps = false;
// Bind the type to the handler
protected array $castHandlers = [
'myDate' => CastMyDate::class,
];
//protected $afterFind = ['checkTransfer'];
protected array $casts = [
'id' => 'int',
'amount' => 'float',
'datum' => 'myDate[dd.MM.yyyy]',
'validate' => 'boolean',
'source_id' => 'int',
];
protected function initialize() {
log_message('debug','mBills initialize');
$this->table = auth()->user()->preFixDB.$this->defaultTableName;
$this->checkOrCreateTable();
}
public function getTable() : string {
return $this->table;
}
// protected function checkTransfer(array $data){
// $data['data']['transfer'] = ((count($this->attributes['details']) == 1) && $accounts->isAccount($this->attributes['details'][0]->account_id));
// }
/**
* liefert Buchungen für Aktivitätenliste
* liefert Buchungen für Aktivitätenliste für alte datentabelle
* @return mixed Datensätze für Tabelle
*/
public function getEntriesDet($start, $ende, $source){
public function getEntriesDet(string $start, string $ende, int $source){
$details = model('App\Models\mBillDetails');
$quelle = model('App\Models\mAccounts');
$this->where('datum >=', date( 'Y-m-d', strtotime($start)));
@@ -51,7 +76,7 @@ class mBills extends Model {
}
}
$result = $this->orderBy('datum','desc')->where('lkz',null)->findAll();
$result = $this->orderBy('datum','desc')->findAll(); //->where('lkz',null)
if (0 == sizeof($result)){
return $result;
}
@@ -64,7 +89,6 @@ class mBills extends Model {
foreach ($result as $value) {
$value->details = $ergebnis[$value->id]??null;
$value->datum = date( "d.m.Y", strtotime( $value->datum ));
$value->source = $quelle->getDropDownEntry($value->source_id);
// $value->amount = number_format( $value->amount , 2, ',', '.' );
}
@@ -72,72 +96,44 @@ class mBills extends Model {
}
/**
* liefert Buchungen für Aktivitätenliste
* @return mixed Datensätze für Tabelle
*/
public function getActivities(string $start, string $ende, int $source){
$quelle = model('App\Models\mAccounts');
$this->where('datum >=', date( 'Y-m-d', strtotime($start)));
$this->where('datum <=', date( 'Y-m-d', strtotime($ende)));
if ($source > 0) {
$this->where('source_id', $source );
}
$result = $this->orderBy('datum','desc')->findAll();
if (0 == sizeof($result)) return $result;
foreach ($result as $value) {
$value->source = $quelle->getDropDownEntry($value->source_id);
}
return $result;
}
/**
* liefert Buchungen für Übersichtstabelle
* @return mixed Datensätze für Tabelle
*/
function getEntries(){
$details = model('App\Models\mBillDetails');
$quelle = model('App\Models\mAccounts');
$result = $this->orderBy('datum','desc')->where('validate',false)->where('lkz',null)->findAll(10);
$keys=array();
foreach ($result as $value) {
$keys[] = intval($value->id);
}
//$ergebnis = $details->whereIn('bill_id', $keys)->asArray()->findAll();
$ergebnis = $details->getDetails($keys);
// print_r($ergebnis);
foreach ($result as $value) {
$value->details = $ergebnis[$value->id]??null;//$details->getEntries($value->id);
$value->datum = date( "d.m.Y", strtotime( $value->datum ));
$value->quelle = $quelle->getDropDownEntry($value->source_id);
// $value->amount = number_format( $value->amount , 2, ',', '.' );
}
public function getEntries(int $zeilen = 10){
$result = $this->orderBy('datum','desc')->where('validate',false)->findAll($zeilen); //->where('lkz',null)
if (0 == sizeof($result)) return $result;
return $result;
}
/**
* liefert gegebene Buchung inkl. Details im Formularformat
* @param int id der Buchung
* @return mixed Datenstruktur für Formular
*/
function getEntry($id, &$result, $accounts){
$details = model('App\Models\mBillDetails');
$quelle = model('App\Models\mAccounts');
$data = $this->orderBy('datum','desc')->find($id);
$result['datum'] = $data->datum;//date( "d.m.Y", strtotime($data->datum));
$result['receiver'] = $data->receiver;
$result['billfile'] = $data->rechnung;
$result['source'] = $data->source_id;
$result['validate'] = $data->validate;
$result['id'] = $id;
$result = array_merge($result, $details->getEntriesForForm($id, $result, $accounts));
$result['transfer'] = $result['transfer'] || ($data->type == 'transfer');
}
public function getToDos(){
$result = $this->orderBy('datum','desc')->where('validate',true)->findAll();
return $result;
}
}
function getToDos(){
$details = model('App\Models\mBillDetails');
$quelle = model('App\Models\mAccounts');
$result = $this->orderBy('datum','desc')->where('validate',true)->where('lkz',null)->findAll();
$keys=array();
foreach ($result as $value) {
$keys[] = intval($value->id);
}
$ergebnis = $details->getDetails($keys);
foreach ($result as $value) {
$value->details = $ergebnis[$value->id]??null;
//$value->details = $details->getEntries($value->id);
$value->datum = date( "d.m.Y", strtotime( $value->datum ));
$value->quelle = $quelle->getDropDownEntry($value->source_id);;
// $value->amount = number_format( $value->amount , 2, ',', '.' );
}
return $result;
}
function getAccountsBalance(){
$sums = $this->db->query("SELECT * FROM get_account_balance4()");
return $sums->getResult();
public function getAccountsBalance(){
$sums = $this->db->query("SELECT * FROM finanzen.getbalances('".auth()->user()->preFixDB."'::text,ARRAY[]::integer[])"); // mit datensyntax ARRAY[210,216]
// log_message('debug', $this->db->getLastQuery());
// log_message('debug', print_r($sums->getResultArray(), true));
return $sums->getResultArray();
}
public function storeBillFile(int $billId, string $filename){
@@ -148,52 +144,49 @@ class mBills extends Model {
$this->update($billId);
}
public function saveBill($data) : int {
$details = model('App\Models\mBillDetails');
$accounts = model('App\Models\mAccounts');
$this->set('datum', date( "Y-m-d", strtotime($data['datum'] ) ));
$this->set('source_id', $data['source']);
$total = floatval($data['total_in'])-floatval($data['total_out']);
if ( !isset($data['multi']) )
$total = floatval($data['input'][0])-floatval($data['output'][0]);
if ( isset($data['rechnung']) )
$this->set('rechnung', $data['rechnung']);
$this->set('amount', $total);
$this->set('validate', $data['validate']??false);
if ($data['transfer']==1){
$this->set('receiver', $accounts->getDropDownEntry($data['category'][0]));
$this->set('type', 'transfer');
}
else{
$this->set('receiver', $data['receiver']);
$this->set('type', 'multiple');
}
//$tabdata['type']
if ( 0 == $data['id'] ){
$this->insert();
$billId = $this->getInsertID();
//insert
}
else{
$billId = $data['id'];
$this->update($data['id']);
}
$details->saveEntries($data, $billId);
return $billId;
}
/**
* löscht gegebene Buchung inkl. Details
* @param int id der Buchung
* @return mixed Datenstruktur für Formular
*/
function deleteEntry($id){
public function deleteEntry(int $id) : bool {
$result = true;
$details = model('App\Models\mBillDetails');
if ($id > 0){
$details->where('bill_id',$id)->delete();
$this->delete($id);
$result = $details->where('bill_id',$id)->delete();
if ($result === true)
$result = $this->delete($id);
}
return $result;
}
public function checkOrCreateTable(){
log_message('debug',"Check or Create Bill Table");
if ($this->db->tableExists('finanzen.'.$this->table)) return;
log_message('debug','Create Bills Table '.$this->db->lastQuery);
log_message('debug',"Create Bills Table ".$this->table);
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
$forge = \Config\Database::forge();
$fields = array(
'id' => array( 'type' => 'serial'),
'datum' => array( 'type' => 'date'),
'receiver' => array( 'type' => 'character varying','constraint' => '120'),
'source_id' => array( 'type' => 'integer' ),
'amount' => array( 'type' => 'numeric','constraint' => '9,2' ),
'validate' => array( 'type' => 'boolean' ),
'rechnung' => array( 'type' => 'character varying','constraint' => '50','null'=>true),
'deleted_at'=> array( 'type' => 'timestamp without time zone','null'=>true),
);
$forge->addField( $fields );
$forge->addPrimaryKey('id');
$forge->addForeignKey('source_id', $accounts->getTable(), 'id','NO ACTION','NO ACTION','source_id_fk');
// $this->db->query("CREATE TABLE $this->table (LIKE $this->defaultTableName INCLUDING DEFAULTS INCLUDING CONSTRAINTS) PARTITION BY RANGE (datum);");
$forge->createTable($this->table,true,['PARTITION BY RANGE'=>'(datum)']);
log_message('debug','Create Bills Table '.$this->db->lastQuery);
// CREATE TABLE temperatures_y2025q1 PARTITION OF temperatures
// FOR VALUES FROM ('2025-01-01') TO ('2025-04-01');
}
};
?>

View File

@@ -3,17 +3,26 @@
use CodeIgniter\Model;
class mScheduled extends Model {
protected $table = 'budget_scheduled';
protected $primaryKey = 'id';
private $defaultTableName='_budget_scheduled';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = false;
protected $useSoftDeletes = true;
protected $deletedField ="deleted_at";
protected $allowedFields = ['creat_date','next_date','data'];
protected $useTimestamps = false;
protected $skipValidation = false;
public function calcNextDate($date, $num, $type)
protected function initialize() {
$this->table = auth()->user()->preFixDB.$this->defaultTableName;
$this->checkOrCreateTable();
}
public function calcNextDate(string $date, string $num, string $type)
{
$start = strtotime( $date );
$period = $num .' '. $type;
@@ -24,68 +33,78 @@ class mScheduled extends Model {
return date( "Y-m-d", $future );
}
public function getEntry($id){
$accounts = model('App\Models\mAccounts');
public function getEntry(int $id){
$data = $this->asObject()->find($id);
$result = (array)json_decode($data->data);
$result['id'] = $id;
$result['datum'] = $data->next_date; //date( "d.m.Y", strtotime($data->next_date));
for ($i=0;$i<10;$i++){
$result['category_parent'][$i]= $accounts->getParent($result['category'][$i]);
}
return $result;
}
public function getEntries(){
$quelle = model('App\Models\mAccounts');
$result = $this->asObject()->findAll();
log_message('error', 'Get Entries Schedules: {msg}', ['msg'=>(string)$this->db->getLastQuery()]);
foreach ($result as $value) {
$details = json_decode($value->data);
for ($i=0;$i<10;$i++){
if ((floatval($details->input[$i]) == 0.0) && (floatval($details->output[$i]) == 0.0))
foreach ($details->input as $key => $line){
if ((floatval($line) == 0.0) && (floatval($details->output[$key]) == 0.0))
continue;
$value->details[] = ['comment'=>$details->comment[$i], 'description'=>$quelle->getDropDownEntry($details->category[$i]), 'subamount'=>(floatval($details->input[$i])-floatval($details->output[$i]))];
// $account_id = (!isset($details->account_id))?$details->category:$details->account_id;
$value->details[] = ['comment'=>$details->comment[$key], 'description'=>$quelle->getDropDownEntry($details->account_id[$key]), 'subamount'=>(floatval($details->input[$key])-floatval($details->output[$key]))];
}
//$value->details = null;
$value->datum = date( "d.m.Y", strtotime( $value->next_date ));
$value->source = $quelle->getDropDownEntry($details->source);
$source_id = (!isset($details->source_id))?$details->source:$details->source_id;
$value->source = $quelle->getDropDownEntry($source_id);
$value->receiver = $details->receiver;
$value->amount = floatval($details->total_in)-floatval($details->total_out);
// $value->amount = number_format( $value->amount , 2, ',', '.' );
// if (!isset($details->amount)){
// $value->amount = floatval($details->total_in)-floatval($details->total_out);
// $value->amount = number_format( floatval($value->amount) , 2, ',', '.' );
// }
// else
$value->amount = $details->amount; //number_format( floatval($details->amount) , 2, ',', '.' );
}
return $result;
}
public function saveBill($data){
public function saveIt(array $data){
$accounts = model('App\Models\mAccounts');
$data['validate'] = true;
$data['scheduled'] = true;
$data['renummer'] = isset($data['renummer']);
if ($data['transfer']==1){
$data['receiver'] = $accounts->getDropDownEntry($data['category'][0]);
$data['transfer'] = true;
}
else{
$data['multi'] = isset($data['multiple']);
$data['transfer'] = false;
}
unset($data['openamount']);
unset($data['category_parent']);
$data['datum'] = date( "Y-m-d", strtotime($data['datum'] ) );
unset($data['total_in']);
unset($data['total_out']);
// $data['datum'] = date( "Y-m-d", strtotime($data['datum'] ) );
$this->set('next_date', $data['datum']);
$data['total_in'] = 0;
$data['total_out'] = 0;
for ($i=0;$i<10;$i++){
if ($data['category'][$i] > 0){
$data['total_in'] += floatval($data['input'][$i]);
$data['total_out'] += floatval($data['output'][$i]);
}
}
$this->set('data',json_encode($data));
log_message("debug","save Scheduled".json_encode($data));
if ( 0 == $data['id']) $this->insert();
else $this->update($data['id']);
}
public function checkOrCreateTable(){
log_message('debug',"Check or Create Scheduled Table");
if ($this->db->tableExists($this->table)) return;
log_message('debug','Create Scheduled Table '.$this->db->lastQuery);
log_message('debug',"Create Scheduled Table ".$this->table);
$forge = \Config\Database::forge();
$fields = array(
'id' => array( 'type' => 'serial'),
'creat_date' => array( 'type' => 'date','default'=>new \CodeIgniter\Database\RawSql('CURRENT_TIMESTAMP')),
'next_date' => array( 'type' => 'date'),
'data' => array( 'type' => 'text'),
'deleted_at'=> array( 'type' => 'timestamp without time zone','null'=>true),
);
$forge->addField( $fields );
$forge->addPrimaryKey('id');
$forge->createTable($this->table,true);
log_message('debug','Create Scheduled Table '.$this->db->lastQuery);
}
}