redesign for mulituser
change validation concept (client and server) using entities
This commit is contained in:
@@ -30,7 +30,12 @@ class Email extends BaseConfig
|
||||
/**
|
||||
* SMTP Server Hostname
|
||||
*/
|
||||
public string $SMTPHost ="web110.dogado.de";
|
||||
public string $SMTPHost = 'web110.dogado.de';
|
||||
|
||||
/**
|
||||
* Which SMTP authentication method to use: login, plain
|
||||
*/
|
||||
public string $SMTPAuthMethod = 'login';
|
||||
|
||||
/**
|
||||
* SMTP Username
|
||||
|
||||
@@ -4,30 +4,37 @@ use CodeIgniter\Router\RouteCollection;
|
||||
|
||||
/** @var RouteCollection $routes */
|
||||
|
||||
|
||||
|
||||
|
||||
// We get a performance increase by specifying the default
|
||||
// route since we don't have to scan directories.
|
||||
$routes->get('/', 'Home::overview');
|
||||
$routes->get('Ajax/(:segment)', 'Ajax::$1');
|
||||
$routes->post('Ajax/(:segment)', 'Ajax::$1');
|
||||
$routes->get('newBill', 'Home::newBill');
|
||||
$routes->get('newTransfer', 'Home::newTransfer');
|
||||
$routes->get('newScheduled', 'Home::newScheduled/0');
|
||||
$routes->get('newScheduledTransfer', 'Home::newScheduled/1');
|
||||
|
||||
//ajax requests for Tableview
|
||||
$routes->get('viewInvoice/(:any)', 'FormHandler::viewInvoice/$1');
|
||||
$routes->post('edit', 'FormHandler::editForm');
|
||||
|
||||
$routes->get('newScheduled', 'Scheduled::new/0');
|
||||
$routes->get('newScheduledTransfer', 'Scheduled::new/1');
|
||||
$routes->get('editScheduled/(:num)', 'Scheduled::edit/$1');
|
||||
$routes->get('getScheduledData', 'Scheduled::getTabData');
|
||||
$routes->post('deleteScheduled', 'Scheduled::delete');
|
||||
$routes->get('syncScheduled', 'Scheduled::sync');
|
||||
$routes->get('viewScheduled', 'Scheduled::viewScheduled');
|
||||
|
||||
|
||||
$routes->post('newBill', 'Home::attemptNewBilling');
|
||||
$routes->post('editAccount', 'Home::attemptEditAccount');
|
||||
$routes->get('editBill/(:num)', 'Home::editBill/$1');
|
||||
$routes->get('editScheduled/(:num)', 'Home::editScheduled/$1');
|
||||
$routes->get('syncScheduled', 'Home::syncScheduled');
|
||||
$routes->get('getOverviewData', 'Bills::getOverviewData');
|
||||
$routes->get('getAccountsBalance', 'Bills::getAccountsBalance');
|
||||
$routes->get('getToDosData', 'Bills::getToDosData');
|
||||
$routes->post('getActivitiesData', 'Bills::getActivitiesData');
|
||||
$routes->get('newBill', 'Bills::edit/0');
|
||||
$routes->get('newTransfer', 'Bills::edit/0/1');
|
||||
$routes->get('editBill/(:num)', 'Bills::edit/$1');
|
||||
$routes->get('viewActivities', 'Bills::viewActivities');
|
||||
$routes->post('deleteBill', 'Bills::delete');
|
||||
|
||||
$routes->post('editAccount', 'Accounts::attemptEditAccount');
|
||||
$routes->match(['GET', 'POST'],'viewAccounts', 'Accounts::index');
|
||||
|
||||
|
||||
$routes->get('viewAccounts', 'Home::viewAccountsTree');
|
||||
$routes->get('viewActivities', 'Home::viewAccountActivities');
|
||||
$routes->get('viewScheduled', 'Home::viewScheduled');
|
||||
$routes->get('viewBill/(:any)', 'Home::viewBill/$1');
|
||||
$routes->get('viewChart', 'Charts::getData/0');
|
||||
$routes->get('viewChart/(:num)', 'Charts::getData/$1');
|
||||
|
||||
|
||||
44
app/Controllers/Accounts.php
Normal file
44
app/Controllers/Accounts.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php namespace App\Controllers;
|
||||
|
||||
use CodeIgniter\Session\Session;
|
||||
use App\Models\mAccounts;
|
||||
use Config\App;
|
||||
|
||||
class Accounts extends BaseController {
|
||||
private \App\Models\mAccounts $accounts;
|
||||
|
||||
public function __construct() {
|
||||
$this->accounts = new mAccounts;
|
||||
}
|
||||
|
||||
public function index(){
|
||||
if ($this->request->is('post')) {
|
||||
return $this->editAccount();
|
||||
}
|
||||
else
|
||||
return $this->viewAccountsTree();
|
||||
}
|
||||
|
||||
private function viewAccountsTree($data = array()){
|
||||
helper('form');
|
||||
$data = array_merge($data,$this->accounts->getTreeData());
|
||||
$data['ddlist'] = $this->accounts->getDropDownList( 'all', false,true );
|
||||
return view('accountstree',$data);
|
||||
}
|
||||
|
||||
private function editAccount(){
|
||||
$rules = [
|
||||
'description' => 'required',
|
||||
];
|
||||
if (! $this->validate($rules)) {
|
||||
return $this->viewAccountsTree(['errors'=>$this->validator->getErrors()]);
|
||||
}
|
||||
$saveDB = array();
|
||||
if ($this->accounts->saveAccount($this->request->getPost()))
|
||||
$saveDB = ['mode'=>'alert-success','message'=>'Erfolgreich gespeichert'];
|
||||
else
|
||||
$saveDB = ['mode'=>'alert-danger','message'=>'Speichern fehlgeschlagen'];
|
||||
|
||||
return $this->viewAccountsTree(['saveDB'=>$saveDB]);
|
||||
}
|
||||
};
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
use App\Models\mBills;
|
||||
use CodeIgniter\Session\Session;
|
||||
|
||||
|
||||
class Ajax extends BaseController
|
||||
{
|
||||
|
||||
protected $session;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->session = service('session');
|
||||
}
|
||||
|
||||
public function getTabelData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
$start = $this->request->getPost('datum_start')??session('datum_start');
|
||||
$ende = $this->request->getPost('datum_ende')??session('datum_ende');
|
||||
$src = intval($this->request->getPost('source')) ?? 0;
|
||||
$_SESSION['datum_start'] = $start;
|
||||
$_SESSION['datum_ende'] = $ende;
|
||||
$_SESSION['source'] = $src;
|
||||
$result = $billing->getEntriesDet($start,$ende,$src);
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
public function getAccountsBalance(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
return json_encode($billing->getAccountsBalance());
|
||||
}
|
||||
|
||||
public function getScheduledData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
return json_encode($scheduled->getEntries());
|
||||
}
|
||||
|
||||
public function getToDosData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
return json_encode($billing->getToDos());
|
||||
}
|
||||
|
||||
public function getOverviewData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
$result = $billing->getEntries();
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
public function deleteBill(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$bills = model('App\Models\mBills');
|
||||
$bills->deleteEntry($this->request->getPost('id'));
|
||||
return json_encode(["result"=>"done"]);
|
||||
}
|
||||
|
||||
public function deleteScheduled(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$scheduled->delete($this->request->getPost('id'));
|
||||
return json_encode(["result"=>"done"]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
90
app/Controllers/Bills.php
Normal file
90
app/Controllers/Bills.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php namespace App\Controllers;
|
||||
|
||||
use App\Models\mAccounts;
|
||||
|
||||
use function PHPUnit\Framework\logicalXor;
|
||||
use App\Models\mBills;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
include_once (dirname(__FILE__) . "/FormHandler.php");
|
||||
|
||||
class Bills extends FormHandler {
|
||||
|
||||
use ResponseTrait;
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function edit(int $id, bool $transfer=false){
|
||||
if ($id == 0){ // erstellen eines leeren Formular
|
||||
log_message('debug','Bills::edit: new bill');
|
||||
$eBooking = new \App\Entities\eBooking();
|
||||
$eBooking->transfer = $transfer;
|
||||
$eBooking->scheduled = false;
|
||||
$data = $eBooking->getNew();
|
||||
} else {
|
||||
$billModel = model(mBills::class);
|
||||
$bill = $billModel->find($id); /* @var \App\Entity\eBooking $bill */
|
||||
$bill->datum = date( "Y-m-d", strtotime( $bill->datum ));
|
||||
$data = $bill->fillDetails();
|
||||
log_message('debug','Bills::edit:ID:'.$id.'; Data: '.json_encode($bill->toArray()));
|
||||
}
|
||||
return $this->viewBill($data);
|
||||
}
|
||||
|
||||
public function viewActivities(){
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$data = array();
|
||||
$data['source'] = 0;
|
||||
$data['start'] = session('datum_start') ?? date("Y-m-d", strtotime( "- 2 weeks", strtotime( "now" ) ));
|
||||
$data['ende'] = session('datum_ende') ?? date("Y-m-d", strtotime( "now" ) );
|
||||
$data['source'] = session('source') ?? 0;
|
||||
$data['sourcelist'] = $accounts->getDropDownList( 'all', true );
|
||||
return view('activities', $data);
|
||||
}
|
||||
|
||||
public function getOverviewData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
$result = $billing->getEntries(10);
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
public function getActivitiesData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
$start = $this->request->getPost('datum_start')??session('datum_start');
|
||||
$ende = $this->request->getPost('datum_ende')??session('datum_ende');
|
||||
$src = intval($this->request->getPost('source'));
|
||||
$_SESSION['datum_start'] = $start;
|
||||
$_SESSION['datum_ende'] = $ende;
|
||||
$_SESSION['source'] = $src;
|
||||
$result = $billing->getEntriesDet($start,$ende,$src);
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
public function delete(){
|
||||
if ($this->request->is('post')) {
|
||||
if (!ctype_digit($this->request->getPost("id"))) return $this->failForbidden("Ungültige ID");
|
||||
log_message('debug',"delete id: ".$this->request->getPost("id"));
|
||||
$billModel = model(mBills::class);
|
||||
$result = $billModel->deleteEntry(intval($this->request->getPost("id")));
|
||||
if ($result !== true)
|
||||
return $this->fail("Database error ".$result);
|
||||
else
|
||||
return $this->respondDeleted(['url'=>session('redirect_url') ?? site_url('/'),'ID'=>$this->request->getPost("id")]);
|
||||
}
|
||||
return $this->failUnauthorized("Schäm Dich");
|
||||
}
|
||||
|
||||
public function getToDosData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
return json_encode($billing->getToDos());
|
||||
}
|
||||
|
||||
public function getAccountsBalance(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$billing = model('App\Models\mBills');
|
||||
return json_encode($billing->getAccountsBalance());
|
||||
}
|
||||
}
|
||||
@@ -10,26 +10,32 @@ class Charts extends BaseController {
|
||||
$this->db = \Config\Database::connect();
|
||||
}
|
||||
|
||||
public function getData($id){
|
||||
public function getData(int $id){
|
||||
if ($id == 0)
|
||||
return $this->getAllData();
|
||||
else
|
||||
return $this->getDetailData($id);
|
||||
}
|
||||
|
||||
private function getDetailData($id){
|
||||
private function getDetailData(int $id){
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$bills = model('App\Models\mBills'); /* @var \App\Models\mBills $bills */
|
||||
$billDet = model('App\Models\mBillDetails'); /* @var \App\Models\mBills $billDet */
|
||||
$accTable = $accounts->getTable();
|
||||
$billTable = $bills->getTable();
|
||||
$billDetTable = $billDet->getTable();
|
||||
$jetzt = date('Y-m-01');
|
||||
$query = <<<EOD
|
||||
SELECT
|
||||
SUM(subamount)*(-1) AS Amount,
|
||||
description,account_id as id
|
||||
FROM
|
||||
finanzen.budget_billdetails, finanzen.budget_bills,finanzen.budget_accounts
|
||||
$billDetTable, $billTable,$accTable
|
||||
WHERE
|
||||
datum >= '$jetzt'
|
||||
AND (datum < '$jetzt'::date + interval '1 month')
|
||||
AND budget_bills.id = bill_id
|
||||
AND account_id = finanzen.budget_accounts.id
|
||||
AND $billTable.id = bill_id
|
||||
AND account_id = $accTable.id
|
||||
AND (account_id IN (
|
||||
WITH RECURSIVE subordinates AS (
|
||||
SELECT
|
||||
@@ -37,7 +43,7 @@ class Charts extends BaseController {
|
||||
parent_id,
|
||||
description
|
||||
FROM
|
||||
finanzen.budget_accounts
|
||||
$accTable
|
||||
WHERE
|
||||
id = $id
|
||||
UNION
|
||||
@@ -46,7 +52,7 @@ class Charts extends BaseController {
|
||||
e.parent_id,
|
||||
e.description
|
||||
FROM
|
||||
finanzen.budget_accounts e
|
||||
$accTable e
|
||||
INNER JOIN subordinates s ON s.id = e.parent_id)
|
||||
SELECT
|
||||
id
|
||||
@@ -72,16 +78,24 @@ class Charts extends BaseController {
|
||||
return view("charts/monthly", $data);
|
||||
}
|
||||
private function getAllData(){
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$bills = model('App\Models\mBills'); /* @var \App\Models\mBills $bills */
|
||||
$billDet = model('App\Models\mBillDetails'); /* @var \App\Models\mBills $billDet */
|
||||
$accTable = $accounts->getTable();
|
||||
$billTable = $bills->getTable();
|
||||
$billDetTable = $billDet->getTable();
|
||||
$jetzt = date('Y-m-01');
|
||||
$query = <<<EOD
|
||||
SELECT * FROM (
|
||||
SELECT id, description,sum(amount)as summe FROM (SELECT id,description from finanzen.budget_accounts WHERE parent_id=0 AND type='output' AND LKZ is null) as w,
|
||||
SELECT id, description,sum(amount)as summe FROM (SELECT id,description from $accTable WHERE parent_id=0 AND account=false AND deleted_at is null) as w,
|
||||
LATERAL
|
||||
(SELECT ABS(SUM(subamount)) as amount
|
||||
FROM finanzen.budget_billdetails, finanzen.budget_bills
|
||||
FROM $billDetTable, $billTable
|
||||
WHERE datum >= '$jetzt'
|
||||
AND budget_bills.id = bill_id
|
||||
AND (account_id IN
|
||||
AND $billTable.deleted_at is null
|
||||
AND $billDetTable.deleted_at is null
|
||||
AND $billTable.id = $billDetTable.bill_id
|
||||
AND (account_id IN
|
||||
(
|
||||
WITH RECURSIVE subordinates AS (
|
||||
SELECT
|
||||
@@ -89,7 +103,7 @@ class Charts extends BaseController {
|
||||
parent_id,
|
||||
description
|
||||
FROM
|
||||
finanzen.budget_accounts
|
||||
$accTable
|
||||
WHERE
|
||||
id = w.id
|
||||
UNION
|
||||
@@ -98,7 +112,7 @@ class Charts extends BaseController {
|
||||
e.parent_id,
|
||||
e.description
|
||||
FROM
|
||||
finanzen.budget_accounts e
|
||||
$accTable e
|
||||
INNER JOIN subordinates s ON s.id = e.parent_id)
|
||||
SELECT
|
||||
id
|
||||
@@ -109,6 +123,7 @@ class Charts extends BaseController {
|
||||
EOD;
|
||||
$data = array();
|
||||
$result = $this->db->query($query);
|
||||
log_message('debug','Charts::getAllData: '.$this->db->getLastQuery());
|
||||
foreach ($result->getResult() as $row) {
|
||||
$werte[] = $row->summe;
|
||||
$ids[] = $row->id;
|
||||
|
||||
195
app/Controllers/FormHandler.php
Normal file
195
app/Controllers/FormHandler.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php namespace App\Controllers;
|
||||
|
||||
use App\Models\mAccounts;
|
||||
|
||||
use function PHPUnit\Framework\logicalXor;
|
||||
use App\Models\mBills;
|
||||
|
||||
|
||||
class FormHandler extends BaseController {
|
||||
|
||||
public function editForm(){
|
||||
if ($this->request->is('post')) {
|
||||
log_message('debug','Bills::edit: post data: '.json_encode($this->request->getPost()));
|
||||
return $this->checkBillForm();
|
||||
}
|
||||
else
|
||||
return $this->viewBill($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft ob Kategorie vorhanden wenn ein Betrag eingegeben wurde, ohne Betrag und ohne Kategorie wird die Zeile ignoriert bzw. gelöscht
|
||||
*/
|
||||
public function _ruleBookingLineAcc($value, array $data, ?string &$error, string $field){
|
||||
log_message('debug',"Bills::_ruleBookingLineAcc Typ von übergegeben Wert".gettype($value));
|
||||
$index = explode('.', $field)[1];
|
||||
if ($value > 0) return true;
|
||||
|
||||
if ($index == 0)
|
||||
$error = "Kategorie fehlt";
|
||||
else if ((is_numeric($data['input'][$index]) && (round($data['input'][$index],2) > 0.0)) || (is_numeric($data['output'][$index]) && (round($data['output'][$index]) > 0.0)))
|
||||
$error = "Kategorie in Zeile " . $index . " fehlt";
|
||||
|
||||
return empty($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft ob Teilbetrag vorhanden wenn eine Kategorie ausgewählt wurde, ohne Betrag und ohne Kategorie wird die Zeile ignoriert bzw. gelöscht
|
||||
* auch wird geprüft dass nur Input oder Output einen Wert enthält, soll im Javascript gemacht werden wenn ordentlich läuft
|
||||
*/
|
||||
public function _ruleBookingLineAmount(string $value, array $data, ?string &$error, string $field){
|
||||
log_message('debug',"Bills::_ruleBookingLineAmount Typ von übergegeben Wert ".gettype($value));
|
||||
$index = explode('.', $field)[1];
|
||||
if ((is_numeric($data['input'][$index]) && (round($data['input'][$index],2) > 0.0)) xor
|
||||
(is_numeric($data['output'][$index]) && (round($data['output'][$index],2) > 0.0)))
|
||||
return true;
|
||||
|
||||
if ((is_numeric($data['input'][$index]) && (round($data['input'][$index],2) > 0.0)) && (is_numeric($data['output'][$index]) && (round($data['output'][$index],2) > 0.0)))
|
||||
$error = "Systemfehler: Nur Input oder Output darf einen Wert haben";
|
||||
|
||||
else if (($index == 0) && (count($data['input'])==1))
|
||||
$error = "Betrag fehlt";
|
||||
else if (is_numeric($data['account_id'][$index]) && ($data['account_id'][$index] > 0))
|
||||
$error = "Betrag in Zeile " . $index+1 . " fehlt";
|
||||
|
||||
return empty($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* rechnet nach ob der Virtuelle Gesamtbetrag (berechnet javascript) stimmt
|
||||
*/
|
||||
public function _ruleCalcAmount(string $value, array $data, ?string &$error, string $field){
|
||||
$subamounts = 0.0;
|
||||
foreach ($data['input'] as $i => $inp){
|
||||
$subamounts = $subamounts + round(floatval($inp),2) - round(floatval($data['output'][$i]),2);
|
||||
}
|
||||
|
||||
if (round($value,2) == round($subamounts,2))
|
||||
return true;
|
||||
else
|
||||
$error = "Systemfehler: Amount Client ". floatval($value) . " ungleich Server Amount ". floatval($subamounts) ." Kalkulation; Diff = ".floatval($value)-floatval($subamounts);
|
||||
|
||||
|
||||
return empty($error);
|
||||
}
|
||||
|
||||
public function _ruleCalcTotal(string $value, array $data, ?string &$error, string $field){
|
||||
log_message('debug',"Bills::_ruleCalcTotal In: ".$data['total_in']."; Out: ".$data['total_out']);
|
||||
|
||||
if ((is_numeric($data['total_in']) && (round($data['total_in'],2) > 0.0)) && (is_numeric($data['total_out']) && (round($data['total_out'],2) > 0.0))) {
|
||||
$error = "Systemfehler: Gesamtbetrag darf nur Input oder Output sein";
|
||||
// } else if ((!is_numeric($data['total_in'])) && (!is_numeric($data['total_out']))) {
|
||||
// $error = "Systemfehler: Gesamtbetrag muss angegeben sein";
|
||||
} else {
|
||||
$total = round(floatval($data['total_in'])-floatval($data['total_out']),2);
|
||||
if (($total !== round(floatval($data['amount']),2)) && (round(floatval($data['openamount']),2) == 0.0))
|
||||
$error = "Systemfehler: Gesamtbetrag entspricht nicht Teilbeträgen";
|
||||
}
|
||||
log_message('debug',"Bills::_ruleCalcTotal Ergebnis ".$error);
|
||||
return empty($error);
|
||||
}
|
||||
|
||||
public function checkBillForm(){
|
||||
$rules = [
|
||||
'id'=>['required','is_natural'],
|
||||
'source_id' => ['label'=>'Konto','rules'=>['required','greater_than[0]'],'errors'=>['greater_than'=>'Konto fehlt']],
|
||||
'datum' => 'required',
|
||||
'scheduled' => 'required',
|
||||
'transfer' => 'required',
|
||||
'sid.*' => ['label'=>'BuchungszeileID','rules'=>['required','is_natural']],
|
||||
'receiver' => ['label'=>'Empfänger','rules'=>['required','max_length[120]'],'errors'=>['required'=>'Empfänger fehlt']],
|
||||
'account_id.*' => [[$this,'_ruleBookingLineAcc']],
|
||||
'input.*' => [[$this,'_ruleBookingLineAmount']],
|
||||
'comment.*' => ['label'=>'Kommentar','rules'=>['max_length[150]']],
|
||||
'output.*' => ['permit_empty','numeric'],
|
||||
'amount' => ['required', 'numeric', [$this,'_ruleCalcAmount']],
|
||||
'billfile' => ['max_size[billfile,10000]','mime_in[billfile,application/pdf,image/jpg,image/jpeg]'],
|
||||
'removeBillFile' => ['max_length[50]'],
|
||||
'validate' => ['required'],
|
||||
'scheduledNum' =>['required_with[scheduled]','permit_empty','numeric'],
|
||||
'scheduledType' =>['required_with[scheduled]','permit_empty','in_list[week,month,year]']
|
||||
];
|
||||
if ( 1 < count($this->request->getPost('sid')) ) {
|
||||
$rules['openamount'] = ['rules'=>['numeric','equals[0.00]'], 'errors'=>['equals'=>'Restbetrag muss 0 sein']];
|
||||
$rules['total_in'] = [[$this,'_ruleCalcTotal']];
|
||||
$rules['total_out'] = ['required_without[total_in]','permit_empty','numeric'];
|
||||
}
|
||||
|
||||
$data = $this->request->getPost();// filter getPost by array_keys($rules) but indexed rules not working
|
||||
log_message('debug','Bills::checkBillForm: Form Data: '.json_encode($data));
|
||||
|
||||
if (! $this->validateData($data, $rules)){
|
||||
log_message('debug','Bills::checkBillForm: validation failed: '.json_encode($data));
|
||||
log_message('debug','Bills::checkBillForm: validation failed: '.json_encode($this->validator->getErrors()));
|
||||
$eBooking = new \App\Entities\eBooking($data);
|
||||
return $this->viewBill($eBooking, $this->validator->getErrors());
|
||||
// return redirect()->back()->withInput()->with('errors', $validation->getErrors());
|
||||
}
|
||||
else{
|
||||
log_message('debug','Bills::checkBillForm: validation success: '.json_encode($this->validator->getValidated()));
|
||||
$eBooking = new \App\Entities\eBooking($this->validator->getValidated());
|
||||
if ($data['scheduled'] == "0"){
|
||||
$file = $this->request->getFile('billfile');
|
||||
if ($file) {
|
||||
if (! $file->isValid() && ($file->getError() != UPLOAD_ERR_NO_FILE)) {
|
||||
throw new \RuntimeException($file->getErrorString() . '(' . $file->getError() . ')');
|
||||
}
|
||||
$eBooking->setInvoice($file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$result = $eBooking->saveIt();
|
||||
if (true !== $result) // show error of database
|
||||
$this->viewBill($eBooking, $result);
|
||||
|
||||
$redirectURL = session('redirect_url') ?? site_url('/');
|
||||
unset($_SESSION['redirect_url']);
|
||||
return redirect()->to($redirectURL);
|
||||
}
|
||||
}
|
||||
|
||||
public function viewBill(\App\Entities\eBooking $fdata, $errors = NULL){
|
||||
helper('form');
|
||||
log_message('debug','Bills::viewBill: fdata: '.json_encode($fdata->toArray()));
|
||||
|
||||
$data['booking'] = $fdata->getFormData();
|
||||
|
||||
$data['validation'] = $errors;
|
||||
return view('newBill', $data);
|
||||
}
|
||||
|
||||
public function viewInvoice(string $filename) {
|
||||
$filePath= WRITEPATH . '/uploads/'.auth()->user()->preFixDB;
|
||||
$file = new \CodeIgniter\Files\File($filePath."/".$filename);
|
||||
log_message('debug',$file->getMimeType());
|
||||
if ($file->getMimeType() == 'application/pdf')
|
||||
$this->viewPdf($filename);
|
||||
else{
|
||||
$imginfo = getimagesize($filePath."/".$filename);
|
||||
header("Content-type: {$imginfo['mime']}");
|
||||
readfile($filePath."/".$filename);
|
||||
exit;
|
||||
}
|
||||
// return view('viewBillImg', ['filename'=>'writable/uploads/'.$filename]);
|
||||
}
|
||||
|
||||
|
||||
private function viewPdf(string $filename) {
|
||||
// $view = \Config\Services::renderer();
|
||||
log_message('debug',$filename);
|
||||
$filePath= WRITEPATH . '/uploads/'.auth()->user()->preFixDB;
|
||||
header("Cache-Control: maxage=1");
|
||||
header("Pragma: public");
|
||||
header('Content-type:application/pdf');
|
||||
header('Content-disposition: inline; filename="'.$filename.'"');
|
||||
header('content-Transfer-Encoding:binary');
|
||||
header('Content-Length:' .filesize($filePath."/".$filename));
|
||||
if (($pdf =file_get_contents($filePath."/".$filename)) === false)
|
||||
print $filePath."/".$filename;
|
||||
else
|
||||
print $pdf;
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,352 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
use App\Models\mBills;
|
||||
use App\Models\mAccounts;
|
||||
use App\Models\mBills;
|
||||
use CodeIgniter\Session\Session;
|
||||
use CodeIgniter\Files\File;
|
||||
use CodeIgniter\I18n\Time;
|
||||
|
||||
class Home extends BaseController
|
||||
{
|
||||
|
||||
private $accounts;
|
||||
class Home extends BaseController {
|
||||
/**
|
||||
* @var Session
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
$this->session = service('session');
|
||||
$this->accounts = model('App\Models\mAccounts');
|
||||
|
||||
}
|
||||
|
||||
public function overview()
|
||||
{
|
||||
public function overview() {
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$bills = model('App\Models\mBills'); /* @var \App\Models\mBills $bills */
|
||||
$billDet = model('App\Models\mBillDetails'); /* @var \App\Models\mBills $billDet */
|
||||
$scheduled = model('App\Models\mScheduled'); /* @var \App\Models\mScheduled $scheduled */
|
||||
return view('table');
|
||||
}
|
||||
|
||||
private function checkDDPList(&$arr, $ele){
|
||||
|
||||
if (!array_key_exists($ele, $arr)){
|
||||
$arr[$ele] = $this->accounts->getDropDownEntry($ele);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkDDSList($arr, $par, $ele){
|
||||
if (!array_key_exists($par, $arr)){
|
||||
$ret = array();
|
||||
if ($ele > 0)
|
||||
$ret[$ele] = $this->accounts->getDropDownEntry($ele);
|
||||
else
|
||||
$ret[0] = '-----';
|
||||
return $ret;
|
||||
}
|
||||
else{
|
||||
return $arr[$par];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function loadFormDefaults(){
|
||||
$data['id'] = 0;
|
||||
$data['source'] = 0;
|
||||
$data['datum'] ='';
|
||||
$data['renummer'] = false;
|
||||
$data['multi'] = false;
|
||||
$data['transfer'] = false;
|
||||
$data['receiver'] = '';
|
||||
$data['total_in'] = '';
|
||||
$data['total_out'] = '';
|
||||
$data['validate'] = false;
|
||||
$data['scheduled'] = false;
|
||||
$data['scheduledNum'] = 0;
|
||||
$data['scheduledType'] = 0;
|
||||
for ($i=0;$i<10;$i++){
|
||||
$data['sid'][$i] = 0;
|
||||
$data['category_parent'][$i] = 0;
|
||||
$data['category'][$i] = 0;
|
||||
$data['input'][$i] = '';
|
||||
$data['output'][$i] = '';
|
||||
$data['comment'][$i] = '';
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legt eine neue Terminbuchung an
|
||||
* @param bool $transfer ob Terminbuchung vom Typ Transfer ist
|
||||
* @return char gibt die View zurück
|
||||
**/
|
||||
public function newScheduled($transfer = 0){
|
||||
$data = $this->loadFormDefaults();
|
||||
$data['transfer'] = (bool)$transfer;
|
||||
return $this->newBill($data,NULL,true);
|
||||
}
|
||||
|
||||
public function newTransfer(){
|
||||
$data = $this->loadFormDefaults();
|
||||
$data['transfer'] = true;
|
||||
return $this->newBill($data,NULL);
|
||||
}
|
||||
|
||||
public function newBill($data = NULL, $errors = NULL,$scheduled = false){
|
||||
helper('form');
|
||||
$data = $data ?? $this->loadFormDefaults();
|
||||
$data['isScheduled'] = $scheduled;
|
||||
$data['validation'] = $errors;
|
||||
|
||||
$srclist = $this->accounts->getDropDownList( 'Acc', TRUE );
|
||||
$this->checkDDPList($srclist,$data['source']);
|
||||
$data['sourcelist'] = $srclist;
|
||||
$data['scheduled'] = array('NumList' => array('1'=>'1','2'=>'2','3'=>'3','4'=>'4','5'=>'5','6'=>'6'),
|
||||
'TypeList' => array('week'=>'Woche(n)','month'=>'Monat(e)','year'=>'Jahr(e)'),
|
||||
'style' => 'class="form-select"');
|
||||
if ($data['transfer'])
|
||||
$categories = $this->accounts->getDropDownLists( 'Acc', TRUE );
|
||||
else
|
||||
$categories = $this->accounts->getDropDownLists( 'InOut', TRUE );
|
||||
|
||||
// $data['catparentlist'] = $categories['parent'];
|
||||
// if (!array_key_exists('catparent', $data))
|
||||
// $data['catparent'] = $this->accounts->getParent($data['cat']);
|
||||
// $this->checkDDPList($data['catparentlist'],$data['catparent']);
|
||||
|
||||
// $data['catlist'] = $this->checkDDSList((array)$categories['subs'],$data['catparent'],$data['cat']);
|
||||
|
||||
$data['subsparent'] = array();
|
||||
$data['subscategory'] = array();
|
||||
for ($i=0;$i<10;$i++){
|
||||
$data['subsparent'][$i] = $categories['parent'];
|
||||
$data['category_parent'][$i] = $data['category_parent'][$i] ?? 0;
|
||||
$this->checkDDPList($data['subsparent'][$i],$data['category_parent'][$i]);
|
||||
$data['subscategory'][$i] = $this->checkDDSList((array)$categories['subs'],$data['category_parent'][$i],$data['category'][$i]??0);
|
||||
}
|
||||
$data['subsdata'] = json_encode($categories['subs']);
|
||||
return view('newBill', $data);
|
||||
}
|
||||
|
||||
private function customValidation(&$errors){
|
||||
$result = true;
|
||||
// if ( "on" == $this->request->getPost('multi') )
|
||||
// {
|
||||
for ($i=0;$i<10;$i++){
|
||||
$inp = $this->request->getPost("input[$i]");
|
||||
$outp = $this->request->getPost("output[$i]");
|
||||
$cat = $this->request->getPost("category[$i]");
|
||||
if ((is_numeric($inp) && $inp > 0.0) || (is_numeric($outp) && $outp > 0.0)){
|
||||
if ($cat == 0){
|
||||
$result &= false;
|
||||
$errors['Kategorie']="Kategorie [$i] fehlt oder ungültig";
|
||||
}
|
||||
}
|
||||
if ($cat > 0){
|
||||
$errors['log2'] = "cat recognized";
|
||||
if (!((is_numeric($inp) && ($inp > 0.0)) || (is_numeric($outp) && ($outp > 0.0)))){
|
||||
$errors['Betrag']="Betrag [$i] fehlt oder ungültig";
|
||||
$result &= false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
// else{
|
||||
// if ((is_numeric($this->request->getPost('total_in')) && $this->request->getPost('total_in') > 0.0) || (is_numeric($this->request->getPost('total_out')) && $this->request->getPost('total_out') > 0.0)){
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// $errors['Betrag']="Betrag fehlt oder ungültig";
|
||||
// }
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function viewBill(string $filename) {
|
||||
$filePath= WRITEPATH . '/uploads';
|
||||
$file = new \CodeIgniter\Files\File($filePath."/".$filename);
|
||||
log_message('debug',$file->getMimeType());
|
||||
if ($file->getMimeType() == 'application/pdf')
|
||||
$this->viewPdf($filename);
|
||||
else{
|
||||
$imginfo = getimagesize($filePath."/".$filename);
|
||||
header("Content-type: {$imginfo['mime']}");
|
||||
readfile($filePath."/".$filename);
|
||||
exit;
|
||||
}
|
||||
// return view('viewBillImg', ['filename'=>'writable/uploads/'.$filename]);
|
||||
}
|
||||
|
||||
|
||||
public function viewPdf(string $filename) {
|
||||
$view = \Config\Services::renderer();
|
||||
log_message('debug',$filename);
|
||||
$filePath= WRITEPATH . '/uploads';
|
||||
header("Cache-Control: maxage=1");
|
||||
header("Pragma: public");
|
||||
header('Content-type:application/pdf');
|
||||
header('Content-disposition: inline; filename="'.$filename.'"');
|
||||
header('content-Transfer-Encoding:binary');
|
||||
header('Content-Length:' .filesize($filePath."/".$filename));
|
||||
if (($pdf =file_get_contents($filePath."/".$filename)) === false)
|
||||
print $filePath."/".$filename;
|
||||
else
|
||||
print $pdf;
|
||||
exit;
|
||||
}
|
||||
|
||||
public function attemptNewBilling()
|
||||
{
|
||||
helper('form');
|
||||
$uploading = false;
|
||||
$rules = [
|
||||
'source' => 'required|greater_than[0]',
|
||||
'datum' => 'required',
|
||||
'category.0' => 'required|greater_than[0]'
|
||||
// 'totalamount'=>'required|numeric'
|
||||
];
|
||||
$errors = [ // Errors
|
||||
'source' => ['required' => 'Konto fehlt','greater_than' => 'Konto fehlt'],
|
||||
'datum' => ['required' => 'Datum fehlt']];
|
||||
// 'totalamount' => ['required' => 'Betrag fehlt','numeric' => 'Betrag muss eine Zahl sein']];
|
||||
if ( 'on' == $this->request->getPost('multi') ) {
|
||||
$rules['openamount'] = 'equals[0]';
|
||||
$errors['openamount'] = ['equals' => 'Betrag muss 0 sein'];
|
||||
}
|
||||
$fehler= array();
|
||||
$valid = $this->customValidation($fehler);
|
||||
$file = $this->request->getFile('billfile');
|
||||
if ($file) {
|
||||
if (! $file->isValid() && ($file->getError() != UPLOAD_ERR_NO_FILE)) {
|
||||
throw new \RuntimeException($file->getErrorString() . '(' . $file->getError() . ')');
|
||||
} else if ($file->isValid()) {
|
||||
$rules['billfile'] = ['uploaded[billfile]','max_size[billfile,10000]','mime_in[billfile,application/pdf,image/jpg,image/jpeg]'];
|
||||
$errors['billfile'] = ['uploaded'=>'Fehler beim Upload','max_size' => 'Zu Groß', 'mime_in' => "Ungültiger Datentyp"];
|
||||
$uploading = true;
|
||||
}
|
||||
}
|
||||
if ((! $this->validate($rules,$errors)) || (!$valid)){
|
||||
return $this->newBill($this->request->getPost(), array_merge($this->validator->getErrors(),$fehler),$this->request->getPost('scheduled'));
|
||||
// return redirect()->back()->withInput()->with('errors', $validation->getErrors());
|
||||
}
|
||||
else{
|
||||
$data = $this->request->getPost();
|
||||
log_message('debug',print_r($data,true));
|
||||
|
||||
if ($this->request->getPost('scheduled') =="0"){
|
||||
$bills = model('App\Models\mBills');
|
||||
if ($this->request->getPost('removeBillFile')){
|
||||
$bills->deleteBillFile($data['id']);
|
||||
unlink(WRITEPATH . 'uploads/'.$this->request->getPost('removeBillFile'));
|
||||
}
|
||||
$billId = $bills->saveBill($data);
|
||||
|
||||
if ($uploading){
|
||||
$date = Time::parse($data['datum']);
|
||||
$file->move(WRITEPATH . 'uploads',$date->toLocalizedString('yyyyMMdd')." ".$data['receiver']." ".$billId.".".$file->guessExtension());
|
||||
log_message('debug', $file->getName());
|
||||
$bills->storeBillFile($billId, $file->getName());
|
||||
}
|
||||
|
||||
$redirectURL = session('redirect_url') ?? site_url('/');
|
||||
unset($_SESSION['redirect_url']);
|
||||
return redirect()->to($redirectURL);
|
||||
}
|
||||
else{
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$scheduled->saveBill($data);
|
||||
}
|
||||
$this->response->redirect(site_url('/'));
|
||||
}
|
||||
}
|
||||
|
||||
public function editBill($id){
|
||||
$bills = model('App\Models\mBills');
|
||||
$data = $this->loadFormDefaults();
|
||||
$result = $bills->getEntry($id, $data, $this->accounts);
|
||||
return $this->newBill($result);
|
||||
}
|
||||
|
||||
public function editScheduled($id){
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$entry = $scheduled->getEntry($id);
|
||||
// $bill = array_merge($this->loadFormDefaults(),(array)json_decode($entry['data']));
|
||||
// $bill['datum'] = $entry['next_date'];
|
||||
return $this->newBill($entry,NULL,true);
|
||||
}
|
||||
|
||||
public function deleteScheduled($id){
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$entry = $scheduled->getEntry($id);
|
||||
// $bill = array_merge($this->loadFormDefaults(),(array)json_decode($entry['data']));
|
||||
// $bill['datum'] = $entry['next_date'];
|
||||
return $this->newBill($entry,NULL,true);
|
||||
}
|
||||
|
||||
public function syncScheduled(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$schedules = $scheduled->findAll();
|
||||
$result = array();
|
||||
$line = "";
|
||||
foreach ( $schedules as $schedule )
|
||||
{
|
||||
$cur_date = $schedule['next_date'];
|
||||
while ( strtotime( $cur_date ) <= strtotime( "now" ) )
|
||||
{
|
||||
$line .= " $cur_date - ";
|
||||
$bill = array_merge($this->loadFormDefaults(),(array)json_decode($schedule['data']));
|
||||
//echo "Hugo:".$schedule['id'];
|
||||
$bill['id']=0; // to generate a new booking
|
||||
$bill['datum'] = $cur_date;
|
||||
$bill['type'] = $bill['transfer']?'transfer':'multiple';
|
||||
$line .= $bill['receiver'];
|
||||
$bills = model('App\Models\mBills');
|
||||
$bills->saveBill($bill);
|
||||
$cur_date = $scheduled->calcNextDate( $cur_date, $bill['scheduledNum'], $bill['scheduledType']);
|
||||
$line .= " - $cur_date <br/>";
|
||||
//log_message('debug','BudgetScheduled:process data: '.logArray($booking->getData()));
|
||||
$scheduled->update($schedule['id'], ['next_date'=>$cur_date ]);
|
||||
|
||||
}
|
||||
}
|
||||
return $line;
|
||||
//$this->showTableBookings();
|
||||
}
|
||||
|
||||
public function viewAccountsTree(){
|
||||
helper('form');
|
||||
$data = $this->accounts->getTreeData();
|
||||
$data['ddlist'] = $this->accounts->getDropDownList( 'all', false,true );
|
||||
return view('accountstree',$data);
|
||||
}
|
||||
|
||||
public function attemptEditAccount(){
|
||||
$rules = [
|
||||
'description' => 'required',
|
||||
'type' => 'required',
|
||||
];
|
||||
if (! $this->validate($rules))
|
||||
{
|
||||
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
|
||||
}
|
||||
$this->accounts->saveAccount($this->request->getPost());
|
||||
// $this->accounts = model('App\Models\mAccounts', false);
|
||||
return $this->viewAccountsTree();
|
||||
|
||||
}
|
||||
|
||||
public function viewAccountActivities(){
|
||||
helper('form');
|
||||
$data = array();
|
||||
$data['source'] = 0;
|
||||
$data['start'] = session('datum_start') ?? date("d.m.Y", strtotime( "- 2 weeks", strtotime( "now" ) ));
|
||||
$data['ende'] = session('datum_ende') ?? date("d.m.Y", strtotime( "now" ) );
|
||||
$data['source'] = session('source') ?? 0;
|
||||
$data['sourcelist'] = $this->accounts->getDropDownList( 'all', TRUE );
|
||||
return view('activities', $data);
|
||||
}
|
||||
|
||||
public function viewScheduled(){
|
||||
helper('form');
|
||||
return view('scheduled');
|
||||
}
|
||||
}
|
||||
|
||||
83
app/Controllers/Scheduled.php
Normal file
83
app/Controllers/Scheduled.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controllers;
|
||||
use App\Models\mScheduled;
|
||||
use CodeIgniter\Session\Session;
|
||||
use CodeIgniter\API\ResponseTrait;
|
||||
include_once (dirname(__FILE__) . "/FormHandler.php");
|
||||
|
||||
class Scheduled extends FormHandler {
|
||||
use ResponseTrait;
|
||||
/**
|
||||
* @var Session
|
||||
*/
|
||||
protected $session;
|
||||
|
||||
public function __construct() {
|
||||
$this->session = service('session');
|
||||
}
|
||||
|
||||
public function new(bool $transfer=false){
|
||||
//log_message('debug','Bills::new');
|
||||
$eBooking = new \App\Entities\eBooking();
|
||||
$eBooking->transfer = $transfer;
|
||||
$eBooking->scheduled = true;
|
||||
$eBooking = $eBooking->getNew();
|
||||
return $this->viewBill($eBooking);
|
||||
}
|
||||
|
||||
public function edit(int $id){
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$entry = $scheduled->getEntry($id);
|
||||
$eBooking = new \App\Entities\eBooking($entry);
|
||||
return $this->viewBill($eBooking);
|
||||
}
|
||||
|
||||
public function sync(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
$schedules = $scheduled->findAll();
|
||||
$lines = "";
|
||||
foreach ( $schedules as $schedule ) {
|
||||
$cur_date = $schedule['next_date'];
|
||||
while ( strtotime( $cur_date ) <= strtotime( "now" ) ) {
|
||||
$data = (array)json_decode($schedule['data']);
|
||||
$data['id'] = 0; // to generate a new booking (overwrite id of scheduled DB)
|
||||
$data['scheduled'] = false;
|
||||
$eBooking = new \App\Entities\eBooking($data);
|
||||
$eBooking->datum = $cur_date;
|
||||
$lines .= " $cur_date - $eBooking->receiver <br/>";
|
||||
$eBooking->saveIt();
|
||||
$cur_date = $scheduled->calcNextDate( $cur_date, $data['scheduledNum'], $data['scheduledType']);
|
||||
}
|
||||
$scheduled->update($schedule['id'], ['next_date'=>$cur_date ]);
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
||||
public function viewScheduled(){
|
||||
helper('form');
|
||||
return view('scheduled');
|
||||
}
|
||||
|
||||
public function delete(){
|
||||
if ($this->request->is('post')) {
|
||||
log_message('debug',"delete id: ".$this->request->getPost("id"));
|
||||
if (!ctype_digit($this->request->getPost("id"))) return $this->failForbidden("Ungültige ID");
|
||||
$schmodel = model(mScheduled::class);
|
||||
$result = $schmodel->delete(intval($this->request->getPost("id")));
|
||||
if ($result !== true)
|
||||
return $this->fail("Database error ".$result);
|
||||
else
|
||||
return $this->respondDeleted(['url'=>session('redirect_url') ?? site_url('/'),'ID'=>$this->request->getPost("id")]);
|
||||
}
|
||||
return $this->failUnauthorized("Schäm Dich");
|
||||
}
|
||||
|
||||
public function getTabData(){
|
||||
if (!$this->request->isAJAX()) return;
|
||||
$scheduled = model('App\Models\mScheduled');
|
||||
return json_encode($scheduled->getEntries());
|
||||
}
|
||||
|
||||
}
|
||||
194
app/Entities/eBooking.php
Normal file
194
app/Entities/eBooking.php
Normal file
@@ -0,0 +1,194 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entities;
|
||||
|
||||
use App\Models\mBills;
|
||||
use App\Models\mBillDetails;
|
||||
use App\Models\mScheduled;
|
||||
use CodeIgniter\Entity\Entity;
|
||||
use CodeIgniter\I18n\Time;
|
||||
|
||||
class eBooking extends Entity{
|
||||
protected $file = null; /* @var \CodeIgniter\HTTP\Files\UploadedFile|null $file */
|
||||
protected $attributes =[
|
||||
'id' => 0,
|
||||
'datum' => '',
|
||||
'source_id' => 0,
|
||||
'receiver' => '',
|
||||
'amount' => null,
|
||||
'validate' => false,
|
||||
'transfer' => false,
|
||||
'scheduled' => false,
|
||||
'details' => [],
|
||||
'deleted_at' => null,
|
||||
'rechnung' => null,
|
||||
'scheduledNum' => null,
|
||||
'scheduledType' => null
|
||||
];
|
||||
|
||||
public function fillDetails(){
|
||||
$billD = model(mBillDetails::class);
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$this->attributes['details'] = $billD->where('bill_id',$this->attributes['id'])->findAll();
|
||||
$this->attributes['scheduled'] = false;
|
||||
$this->attributes['transfer'] = ((count($this->attributes['details']) == 1) && $accounts->isAccount($this->attributes['details'][0]->account_id));
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setInvoice(\CodeIgniter\HTTP\Files\UploadedFile $file){
|
||||
$this->file = $file;
|
||||
}
|
||||
|
||||
public function getNew(){
|
||||
$this->attributes['datum'] = date('Y-m-d');
|
||||
$this->attributes['details'][] = new \App\Entities\eBookingLine();
|
||||
log_message('debug','eBooking::getNew: '.json_encode($this->attributes));
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFormData(){
|
||||
$billDet = new \App\Entities\eBookingLine();
|
||||
$data = $this->toArray();
|
||||
$data['template'] = $billDet->toArray();
|
||||
log_message('debug','eBooking::getFormData:template '.json_encode($data['template']));
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$data['category'] = $accounts->getDropDownLists($this->attributes['transfer']?'Acc':'InOut');
|
||||
$data['sourcelist'] = $accounts->getDropDownList( type:'Acc', defaultKey:$data['source_id'] );
|
||||
// log_message('debug','eBooking::getFormData: '.json_encode($data));
|
||||
//$billDet->createDropDownLists($data);
|
||||
|
||||
if (is_null($this->attributes['amount'])){
|
||||
$data['total_in'] = '';
|
||||
$data['total_out'] = '';
|
||||
}
|
||||
else {
|
||||
$data['total_in'] = ($this->attributes['amount'] >= 0.0)? abs($this->attributes['amount']):'';
|
||||
$data['total_out'] = ($this->attributes['amount'] < 0.0)? abs($this->attributes['amount']):'';
|
||||
}
|
||||
|
||||
if ($this->attributes['scheduled']??false){
|
||||
// $data['scheduledNum'] = 0;
|
||||
// $data['scheduledType'] = 0;
|
||||
$data['schedule_lists'] = array('NumList' => array('1'=>'1','2'=>'2','3'=>'3','4'=>'4','5'=>'5','6'=>'6'),
|
||||
'TypeList' => array('week'=>'Woche(n)','month'=>'Monat(e)','year'=>'Jahr(e)'));
|
||||
}
|
||||
|
||||
if (count($this->attributes['details'])>0){
|
||||
foreach ($this->attributes['details'] as $i => $line){
|
||||
$line->createFormData($data,$i);
|
||||
}
|
||||
}else{
|
||||
foreach ($this->attributes['sid'] as $i => $line){
|
||||
$billDet->createDropDownLists($data,$i);
|
||||
}
|
||||
}
|
||||
log_message('debug','eBooking::getFormData: '.json_encode($data));
|
||||
return $data;
|
||||
}
|
||||
|
||||
// public function convertFromPost(array $data){
|
||||
// $this->fill($data);
|
||||
// foreach ($data['sid'] as $i => $value){
|
||||
// $sub = array('id' => $value,
|
||||
// 'bill_id' => $data['id'],
|
||||
// 'comment' => $data['comment'][$i],
|
||||
// 'account_id' => $data['account_id'][$i],
|
||||
// 'subamount' => floatval($data['input'][$i])-floatval($data['output'][$i]),
|
||||
// 'deleted_at' => null);
|
||||
// $details[] = new \App\Entities\eBookingLine($sub);
|
||||
// }
|
||||
// }
|
||||
|
||||
private function calcAmount(){
|
||||
$amount = floatval($data['total_in'])-floatval($data['total_out']);
|
||||
$subamounts = 0.0;
|
||||
foreach ($this->attributes['input'] as $i => $value){
|
||||
$subamounts = $subamounts + floatval($value) - floatval($this->attributes['output'][$i]);
|
||||
}
|
||||
}
|
||||
|
||||
private function saveScheduled() {
|
||||
$scheduledModel = model(mScheduled::class);
|
||||
$data = $this->toArray();
|
||||
for ($i=(count($data['account_id'])-1); $i>0; $i--){
|
||||
if ($data['account_id'][$i] == "0") {
|
||||
unset($data['account_id'][$i]);
|
||||
unset($data['sid'][$i]);
|
||||
unset($data['input'][$i]);
|
||||
unset($data['output'][$i]);
|
||||
unset($data['comment'][$i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $scheduledModel->saveIt($data);
|
||||
|
||||
}
|
||||
//switch scheduled or bill
|
||||
|
||||
public function saveIt() {
|
||||
if ($this->attributes['scheduled'] != 0) return $this->saveScheduled();
|
||||
|
||||
$billModel = model(mBills::class);
|
||||
|
||||
if ($this->attributes['id'] == 0) {
|
||||
|
||||
$billId = $billModel->insert($this, true);
|
||||
log_message('debug','SaveIt with insert result: '.json_encode($billId));
|
||||
if ($billId === false)
|
||||
return $billModel->errors();
|
||||
else{
|
||||
$this->attributes['id'] = $billId;
|
||||
}
|
||||
//$billId = $$billModel->getInsertID();
|
||||
} else {
|
||||
if ($this->attributes['removeBillFile']??false){
|
||||
$this->attributes['rechnung'] = null;
|
||||
unlink(WRITEPATH . 'uploads/'.auth()->user()->preFixDB.'/'.$this->attributes['removeBillFile']);
|
||||
}
|
||||
if ($billModel->update($this->attributes['id'],$this) === false)
|
||||
return $billModel->errors();
|
||||
}
|
||||
|
||||
$billDetailsModel = model(mBillDetails::class);
|
||||
$details = new \App\Entities\eBookingLine;
|
||||
foreach ($this->attributes['sid'] as $i => $value){
|
||||
if ($this->attributes['account_id'][$i] == 0) { // leere Zeile ignorieren bzw wenn id (also bereits in DB) dann löschen
|
||||
if ($value == 0) {
|
||||
continue;
|
||||
} else {
|
||||
$billDetailsModel->delete($value);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$sub = array('sid' => ($value == 0)? NULL: $value,
|
||||
'bill_id' => $this->attributes['id'],
|
||||
'comment' => $this->attributes['comment'][$i],
|
||||
'account_id' => $this->attributes['account_id'][$i],
|
||||
'subamount' => floatval($this->attributes['input'][$i])-floatval($this->attributes['output'][$i]),
|
||||
'deleted_at' => null);
|
||||
$details->fill($sub);
|
||||
$billDetailsModel->save($details);
|
||||
}
|
||||
|
||||
if ($this->file) {
|
||||
if (! $this->file->isValid() && ($this->file->getError() != UPLOAD_ERR_NO_FILE)) {
|
||||
throw new \RuntimeException($this->file->getErrorString() . '(' . $this->file->getError() . ')');
|
||||
} else if ($this->file->isValid()) {
|
||||
helper('url');
|
||||
$date = Time::parse($this->attributes['datum']);
|
||||
$name = url_title($date->toLocalizedString('yyyyMMdd')." ".$this->attributes['receiver']." ".$this->attributes['id']);
|
||||
$this->file->move(WRITEPATH . 'uploads/'.auth()->user()->preFixDB,$name.".".$this->file->guessExtension());
|
||||
log_message('debug', $this->file->getName());
|
||||
$this->attributes['rechnung'] = $this->file->getName();
|
||||
if ($billModel->update($this->attributes['id'],$this) === false)
|
||||
return $billModel->errors();
|
||||
}
|
||||
}
|
||||
|
||||
// $details = model('App\Models\mBillDetails');
|
||||
// return $details->getDetails([$this->id]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
69
app/Entities/eBookingLine.php
Normal file
69
app/Entities/eBookingLine.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entities;
|
||||
|
||||
use CodeIgniter\Entity\Entity;
|
||||
use App\Models\mAccounts;
|
||||
|
||||
class eBookingLine extends Entity{
|
||||
protected $attributes =[
|
||||
'id' => 0,
|
||||
'bill_id' => 0,
|
||||
'comment' => '',
|
||||
'account_id' => 0,
|
||||
'subamount' => null,
|
||||
'deleted_at' => null,
|
||||
];
|
||||
|
||||
protected $datamap = [
|
||||
// property_name => db_column_name
|
||||
'sid' => 'id',
|
||||
];
|
||||
private function checkCreateParentDefault(array &$list, int $parentId) : void {
|
||||
if ($parentId == 0) return;
|
||||
if (!array_key_exists($parentId, $list)){
|
||||
log_message('debug',"Parent not exists: $parentId in List: ".json_encode(array_keys($list)));
|
||||
$list[$parentId] = $this->accounts->getDropDownEntry($parentId);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkCreateSubDefault(array &$list, int $accountId) : void {
|
||||
if (!array_key_exists($accountId, $list)){
|
||||
if ($accountId > 0)
|
||||
$list[$accountId] = $this->accounts->getDropDownEntry($accountId);
|
||||
else
|
||||
$list[0] = '-----';
|
||||
}
|
||||
}
|
||||
|
||||
public function createFormData(array &$data, int $i){
|
||||
if (!array_key_exists('sid', $data)) $data['sid'] = [];
|
||||
if (!array_key_exists('comment', $data)) $data['comment'] = [];
|
||||
if (!array_key_exists('account_id', $data)) $data['account_id'] = [];
|
||||
if (!array_key_exists('deleted_at', $data)) $data['deleted_at'] = [];
|
||||
if (!array_key_exists('input', $data)) $data['input'] = [];
|
||||
if (!array_key_exists('output', $data)) $data['output'] = [];
|
||||
|
||||
$data['sid'][$i] = $this->attributes['id'];
|
||||
$data['comment'][$i] = $this->attributes['comment'];
|
||||
$data['account_id'][$i] = $this->attributes['account_id'];
|
||||
$data['deleted_at'][$i] = $this->attributes['deleted_at'];
|
||||
$data['input'][$i] = (!is_null($this->attributes['subamount']) && $this->attributes['subamount'] > 0.0) ? $this->attributes['subamount'] :'';
|
||||
$data['output'][$i] = (!is_null($this->attributes['subamount']) && $this->attributes['subamount'] <= 0.0) ? abs($this->attributes['subamount']) :'';
|
||||
$this->createDropDownLists($data,$i);
|
||||
}
|
||||
|
||||
public function createDropDownLists(array &$data, int $i){
|
||||
$accounts = model('App\Models\mAccounts'); /* @var \App\Models\mAccounts $accounts */
|
||||
$lists = $data['category'] ?? [];
|
||||
if (!array_key_exists('parent_id', $data)) $data['parent_id'] = [];
|
||||
if (!array_key_exists('cat_parent', $data)) $data['cat_parent'] = [];
|
||||
if (!array_key_exists('cat_sub', $data)) $data['cat_sub'] = [];
|
||||
|
||||
$data['parent_id'][$i] = $accounts->getParent($data['account_id'][$i]);
|
||||
$data['cat_parent'][$i] = $lists['parent'];
|
||||
$this->checkCreateParentDefault($data['cat_parent'][$i],$data['parent_id'][$i]);
|
||||
$data['cat_sub'][$i] = $lists['subs']->{$data['parent_id'][$i]} ?? [];
|
||||
$this->checkCreateSubDefault($data['cat_sub'][$i],$data['account_id'][$i]);
|
||||
}
|
||||
}
|
||||
78
app/Language/de/Validation.php
Normal file
78
app/Language/de/Validation.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of CodeIgniter 4 framework.
|
||||
*
|
||||
* (c) CodeIgniter Foundation <admin@codeigniter.com>
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// Validation language settings
|
||||
return [
|
||||
// Core Messages
|
||||
'noRuleSets' => 'No rule sets specified in Validation configuration.',
|
||||
'ruleNotFound' => '"{0}" is not a valid rule.',
|
||||
'groupNotFound' => '"{0}" is not a validation rules group.',
|
||||
'groupNotArray' => '"{0}" rule group must be an array.',
|
||||
'invalidTemplate' => '"{0}" is not a valid Validation template.',
|
||||
|
||||
// Rule Messages
|
||||
'alpha' => 'The {field} field may only contain alphabetical characters.',
|
||||
'alpha_dash' => 'The {field} field may only contain alphanumeric, underscore, and dash characters.',
|
||||
'alpha_numeric' => 'The {field} field may only contain alphanumeric characters.',
|
||||
'alpha_numeric_punct' => 'The {field} field may contain only alphanumeric characters, spaces, and ~ ! # $ % & * - _ + = | : . characters.',
|
||||
'alpha_numeric_space' => 'The {field} field may only contain alphanumeric and space characters.',
|
||||
'alpha_space' => 'The {field} field may only contain alphabetical characters and spaces.',
|
||||
'decimal' => 'The {field} field must contain a decimal number.',
|
||||
'differs' => 'The {field} field must differ from the {param} field.',
|
||||
'equals' => 'Das Feld {field} muss exakt sein: {param}.',
|
||||
'exact_length' => 'The {field} field must be exactly {param} characters in length.',
|
||||
'field_exists' => 'The {field} field must exist.',
|
||||
'greater_than' => 'The {field} field must contain a number greater than {param}.',
|
||||
'greater_than_equal_to' => 'The {field} field must contain a number greater than or equal to {param}.',
|
||||
'hex' => 'The {field} field may only contain hexadecimal characters.',
|
||||
'in_list' => 'The {field} field must be one of: {param}.',
|
||||
'integer' => 'The {field} field must contain an integer.',
|
||||
'is_natural' => 'The {field} field must only contain digits.',
|
||||
'is_natural_no_zero' => 'The {field} field must only contain digits and must be greater than zero.',
|
||||
'is_not_unique' => 'The {field} field must contain a previously existing value in the database.',
|
||||
'is_unique' => 'The {field} field must contain a unique value.',
|
||||
'less_than' => 'The {field} field must contain a number less than {param}.',
|
||||
'less_than_equal_to' => 'The {field} field must contain a number less than or equal to {param}.',
|
||||
'matches' => 'The {field} field does not match the {param} field.',
|
||||
'max_length' => '{field} darf nicht länger als {param} Zeichen sein.',
|
||||
'min_length' => 'The {field} field must be at least {param} characters in length.',
|
||||
'not_equals' => 'The {field} field cannot be: {param}.',
|
||||
'not_in_list' => 'The {field} field must not be one of: {param}.',
|
||||
'numeric' => 'Das Feld {field} darf nur Zahlen enthalten.',
|
||||
'regex_match' => 'The {field} field is not in the correct format.',
|
||||
'required' => 'Das Feld {field} ist erforderlich.',
|
||||
'required_with' => 'The {field} field is required when {param} is present.',
|
||||
'required_without' => 'Das Feld {field} muss ausgefüllt werden, wenn {param} nicht vorhanden ist.',
|
||||
'string' => 'The {field} field must be a valid string.',
|
||||
'timezone' => 'The {field} field must be a valid timezone.',
|
||||
'valid_base64' => 'The {field} field must be a valid base64 string.',
|
||||
'valid_email' => 'The {field} field must contain a valid email address.',
|
||||
'valid_emails' => 'The {field} field must contain all valid email addresses.',
|
||||
'valid_ip' => 'The {field} field must contain a valid IP.',
|
||||
'valid_url' => 'The {field} field must contain a valid URL.',
|
||||
'valid_url_strict' => 'The {field} field must contain a valid URL.',
|
||||
'valid_date' => 'The {field} field must contain a valid date.',
|
||||
'valid_json' => 'The {field} field must contain a valid json.',
|
||||
|
||||
// Credit Cards
|
||||
'valid_cc_number' => '{field} does not appear to be a valid credit card number.',
|
||||
|
||||
// Files
|
||||
'uploaded' => '{field} is not a valid uploaded file.',
|
||||
'max_size' => '{field} is too large of a file.',
|
||||
'is_image' => '{field} is not a valid, uploaded image file.',
|
||||
'mime_in' => '{field} does not have a valid mime type.',
|
||||
'ext_in' => '{field} does not have a valid file extension.',
|
||||
'max_dims' => '{field} is either not an image, or it is too wide or tall.',
|
||||
'min_dims' => '{field} is either not an image, or it is not wide or tall enough.',
|
||||
];
|
||||
49
app/Models/Cast/CastMyDate.php
Normal file
49
app/Models/Cast/CastMyDate.php
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
?>
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
?>
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
?>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,13 @@
|
||||
<div class="card text-bg-dark">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<form class="form form-vertical" id="editaccount" method="post" action="<?= base_url() ?>/editAccount">
|
||||
<form class="form form-vertical" id="editaccount" method="post" action="<?= base_url() ?>/viewAccounts">
|
||||
<input type="hidden" value="<?= $id??0 ?>" name="id" id="id">
|
||||
<?php if (! empty($validation)) : ?>
|
||||
<?php if (! empty($errors)) : ?>
|
||||
<div class='alert alert-danger mt-2'>
|
||||
<div class="errors" role="alert">
|
||||
<ul>
|
||||
<?php foreach ($validation as $error) : ?>
|
||||
<?php foreach ($errors as $error) : ?>
|
||||
<li><?= esc($error) ?></li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
@@ -26,33 +26,36 @@
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="parent">Überkonto:</label>
|
||||
<?= form_dropdown('parent', $ddlist, $parent??0,'id="parent" class="form-select"'); ?>
|
||||
<select name="parent" class="form-select" required id="parent" >
|
||||
<option value="0">----</option>
|
||||
<?php foreach ($ddlist as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == ($parent??0))?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="typeAccount" value="account" name="type" <?= set_radio('type', 'account') ?>>
|
||||
<label class="form-check-label" for="inlineCheckbox1">Konto</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="typeInput" value="input" name="type" <?= set_radio('type', 'input') ?> >
|
||||
<label class="form-check-label" for="inlineCheckbox2">Einnahmen</label>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input class="form-check-input" type="checkbox" id="typeOutput" value="output" name="type" <?= set_radio('type', 'output', true) ?> >
|
||||
<label class="form-check-label" for="inlineCheckbox3">Ausgaben</label>
|
||||
<div class="form-check form-switch">
|
||||
<label class="form-check-label" for="account">Typ Konto</label>
|
||||
<input class="form-check-input" type="checkbox" id="account" name="account" <?= set_checkbox('account', 'on', $account??false) ?> >
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch">
|
||||
<label class="form-check-label" for="bookable">Buchbarkeit</label>
|
||||
<input class="form-check-input" type="checkbox" id="bookable" value="bookable" name="bookable" <?= set_checkbox('bookable', 'on', (($bookable??"f")=="t")?true:false) ?> >
|
||||
<input class="form-check-input" type="checkbox" id="bookable" value="bookable" name="bookable" <?= set_checkbox('bookable', 'on', $bookable??false) ?> >
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch">
|
||||
<label class="form-check-label" for="lkz">lkz</label>
|
||||
<input class="form-check-input" type="checkbox" id="lkz" value="1" name="lkz" <?= set_checkbox('lkz', '1', $lkz??false) ?>>
|
||||
<label class="form-check-label" for="monitor">Monitor</label>
|
||||
<input class="form-check-input" type="checkbox" id="monitor" name="monitor" <?= set_checkbox('monitor', 'on', $monitor??false) ?> >
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-check form-switch">
|
||||
<label class="form-check-label" for="deleted_at">Gelöscht</label>
|
||||
<input class="form-check-input" type="checkbox" id="deleted_at" value="1" name="deleted_at" <?= set_checkbox('deleted_at', '1', $deleted_at??false) ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
|
||||
@@ -3,31 +3,49 @@
|
||||
|
||||
<?= $this->section('css'); ?>
|
||||
<link rel="stylesheet" href="/css/mawim.css">
|
||||
<link rel="stylesheet" href="/assets/jquery-ui-1.13.2.custom/jquery-ui.css">
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('menu'); ?>
|
||||
<?= $this->include('sidebar') ?>
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('content'); ?>
|
||||
<?php if (!function_exists('printBool')) {
|
||||
function printBool(bool $var){
|
||||
return ($var)?"true":"false";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php function printsub($id, $all){
|
||||
<?php if (!function_exists('printsub')) { function printsub(int $id, $all){
|
||||
$liste = '';
|
||||
$ret='';
|
||||
foreach($all as $ele){
|
||||
$class ="";
|
||||
$vis ="d-none";
|
||||
if ($ele->parent_id == $id){
|
||||
if ($ele->lkz) $class = "text-bg-danger";
|
||||
else if ($ele->bookable == "f") $class = "text-bg-warning";
|
||||
$toolt ="bookable: $ele->bookable; lkz: $ele->lkz; Id: $ele->id; PID:$ele->parent_id";
|
||||
$liste .= "<li><span data-bs-toggle='tooltip' data-bs-html=true title='$toolt'";
|
||||
if ($ele->deleted_at) {
|
||||
$class = "text-bg-danger";
|
||||
$vis="d-none";
|
||||
}
|
||||
else {
|
||||
$vis="";
|
||||
if (!$ele->bookable)
|
||||
$class = "text-bg-warning";
|
||||
}
|
||||
$toolt = ($ele->bookable)?"":"not ";
|
||||
$toolt .= "bookable; ";
|
||||
$toolt .= ($ele->deleted_at)?"gelöscht; ":"";
|
||||
$toolt .="Id: $ele->id; PID:$ele->parent_id";
|
||||
$liste .= "<li class=\"$vis\"><i class=\"fa-solid\"></i> <span data-bs-toggle='tooltip' data-bs-html=true title='$toolt'";
|
||||
$liste .= "data-id=\"$ele->id\"";
|
||||
$liste .= "data-pid=\"$ele->parent_id\"";
|
||||
$liste .= "data-bookable=\"$ele->bookable\"";
|
||||
$liste .= "data-lkz=\"$ele->lkz\"";
|
||||
$liste .= "data-type=\"$ele->type\"";
|
||||
$liste .= "data-bookable=\"".printBool($ele->bookable)."\"";
|
||||
$liste .= "data-account=\"".printBool($ele->account)."\"";
|
||||
$liste .= "data-monitor=\"".printBool($ele->monitor)."\"";
|
||||
$liste .= "data-deleted=\"$ele->deleted_at\"";
|
||||
$liste .= "data-description=\"$ele->description\"";
|
||||
$liste .= "class='$class'>$ele->description</span></li>";
|
||||
$liste .= "class='$class'>$ele->description</span>";
|
||||
$liste .= printsub($ele->id, $all);
|
||||
$liste .= "</li>";
|
||||
}
|
||||
}
|
||||
if ($liste !=''){
|
||||
@@ -36,33 +54,53 @@
|
||||
$ret .= "</ul>";
|
||||
}
|
||||
return $ret;
|
||||
} ?>
|
||||
}} ?>
|
||||
<div class="page-heading">
|
||||
<h3> Kategorien bearbeiten</h3>
|
||||
<?php if ($saveDB??false) : ?>
|
||||
<div class='alert <?= $saveDB["mode"] ?> mt-2'>
|
||||
<?= $saveDB["message"] ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-12" id="tree">
|
||||
<div class="card text-bg-dark">
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<div><a class="btn btn-info multi" onclick="newCat();" role="button">Neue Kategorie</a></div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<a class="btn btn-info multi" onclick="newCat();" role="button"> + Neue Kategorie</a>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6 form-check form-check-reverse form-switch justify-content-end">
|
||||
<input class="form-check-input" type="checkbox" id="viewdeleted" value="1" name="viewdeleted">
|
||||
<label class="form-check-label" for="viewdeleted">Gelöschte</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tree">
|
||||
<ul>
|
||||
<?php foreach($parents as $parent): ?>
|
||||
<?php $class='';
|
||||
if ($parent->lkz) $class = "text-bg-danger";
|
||||
else if ($parent->bookable == "f") $class = "text-bg-warning"; ?>
|
||||
<li> <span data-bs-toggle='tooltip'
|
||||
<?php $class=''; $vis ="d-none";
|
||||
if ($parent->deleted_at) {
|
||||
$class = "text-bg-danger";
|
||||
$vis = "d-none";
|
||||
} else {
|
||||
$vis = "";
|
||||
if (!$parent->bookable) $class = "text-bg-warning";
|
||||
}?>
|
||||
<li class="<?=$vis?>"><i class="fa-solid"></i> <span data-bs-toggle='tooltip'
|
||||
data-bs-html=true
|
||||
data-id="<?=$parent->id?>"
|
||||
data-pid="0"
|
||||
data-bookable="<?=$parent->bookable?>"
|
||||
data-lkz=" <?= $parent->lkz?>"
|
||||
data-type="<?= $parent->type?>"
|
||||
data-bookable=<?=printBool($parent->bookable)?>
|
||||
data-monitor=<?=printBool($parent->monitor)?>
|
||||
data-account=<?=printBool($parent->account)?>
|
||||
data-deleted="<?= $parent->deleted_at?>"
|
||||
data-description="<?= $parent->description?>";
|
||||
title="bookable: <?=$parent->bookable?>; lkz: <?= $parent->lkz?>; Id: <?=$parent->id?>;" class="<?=$class?>"><?=$parent->description?></span>
|
||||
title="<?=($parent->bookable)?"":"not "?>bookable; <?= ($parent->deleted_at)?"gelöscht; ":""?>Id: <?=$parent->id?>;"
|
||||
class="<?=$class?>"><?=$parent->description?></span>
|
||||
<?= printsub($parent->id, $all); ?>
|
||||
|
||||
<li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -70,13 +108,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-12 d-none" id="editor">
|
||||
<div class="col-md-3 col-12 <?= (empty($errors))?"d-none" :"" ?>" id="editor">
|
||||
<?= $this->include('accountsform') ?>
|
||||
</div>
|
||||
</section>
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('scripts'); ?>
|
||||
<script src="/assets/jquery-ui-1.13.2.custom/jquery-ui.js"></script>
|
||||
<script></script>
|
||||
<script src="/js/accounts.js"></script>
|
||||
<?= $this->endSection(); ?>
|
||||
@@ -1,7 +1,6 @@
|
||||
<?= $this->extend('layout'); ?>
|
||||
|
||||
<?= $this->section('css'); ?>
|
||||
<link rel="stylesheet" href="/assets/jquery-ui-1.13.2.custom/jquery-ui.css">
|
||||
<link rel="stylesheet" href="/css/mawim.css">
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('menu'); ?>
|
||||
@@ -13,71 +12,40 @@
|
||||
<div class="row">
|
||||
<div class="col-xxl-8 col-12">
|
||||
<div class="text-white-50"><h2>Verlauf</h2></div>
|
||||
<form class="form row row-cols align-items-bottom" id="getData" method="post" action="<?= base_url() ?>/Ajax/getTabelData">
|
||||
<form class="form row row-cols align-items-bottom" id="getData" method="post" action="/getActivitiesData">
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-12">
|
||||
<input type="text" class="form-control" id="datepickers" data-date-format="mm.dd.yyyy" name="datum_start" placeholder="Datum Start" value="<?= $datum_start??$start ?>"/>
|
||||
<input type="date" class="form-control" name="datum_start" placeholder="Datum Start" value="<?= $datum_start??$start ?>"/>
|
||||
</div>
|
||||
<div class="col-lg-3 col-12">
|
||||
<input type="text" class="form-control" id="datepickere" data-date-format="mm.dd.yyyy" name="datum_ende" placeholder="Datum Ende" value="<?= $datum_ende??$ende ?>"/>
|
||||
<input type="date" class="form-control" name="datum_ende" placeholder="Datum Ende" value="<?= $datum_ende??$ende ?>"/>
|
||||
</div>
|
||||
<div class="col-lg-3 col-12">
|
||||
<div class="form-group">
|
||||
<?= form_dropdown('source', $sourcelist, $source,'id="source" class="form-select"'); ?>
|
||||
<select name="source" class="form-select">
|
||||
<option value="0">----</option>
|
||||
<?php foreach ($sourcelist as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == $source)?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-12">
|
||||
<a class="btn btn-primary" onclick="datatable.ajax.reload();" role="button">Aktualisieren</a>
|
||||
<a class="btn btn-primary" onclick="loadActivityData();" role="button">Aktualisieren</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-sm table-striped" id="bookings" cellspacing="0"></table>
|
||||
<table id="activities" cellspacing="0"></table>
|
||||
</div>
|
||||
<div class="col-xxl-4 col-12 d-none d-xxl-block">
|
||||
<div class="text-white-50"><h2>Aktuelle Kontostände</h2></div>
|
||||
<table class="table table-striped table-sm" id="accounts" cellspacing="0"></table>
|
||||
<table id="accounts" cellspacing="0"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('scripts'); ?>
|
||||
<script src="/assets/jquery-ui-1.13.2.custom/jquery-ui.js"></script>
|
||||
<script>
|
||||
$.datepicker.regional['de'] = {clearText: 'löschen', clearStatus: 'aktuelles Datum löschen',
|
||||
closeText: 'schließen', closeStatus: 'ohne Änderungen schließen',
|
||||
prevText: '<zurück', prevStatus: 'letzten Monat zeigen',
|
||||
nextText: 'Vor>', nextStatus: 'nächsten Monat zeigen',
|
||||
currentText: 'heute', currentStatus: '',
|
||||
monthNames: ['Januar','Februar','März','April','Mai','Juni',
|
||||
'Juli','August','September','Oktober','November','Dezember'],
|
||||
monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
|
||||
'Jul','Aug','Sep','Okt','Nov','Dez'],
|
||||
monthStatus: 'anderen Monat anzeigen', yearStatus: 'anderes Jahr anzeigen',
|
||||
weekHeader: 'Wo', weekStatus: 'Woche des Monats',
|
||||
dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
|
||||
dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
|
||||
dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
|
||||
dayStatus: 'Setze DD als ersten Wochentag', dateStatus: 'Wähle D, M d',
|
||||
dateFormat: 'dd.mm.yy', firstDay: 1,
|
||||
initStatus: 'Wähle ein Datum', isRTL: false};
|
||||
$.datepicker.setDefaults($.datepicker.regional['de']);
|
||||
$('#datepickers').datepicker(
|
||||
{
|
||||
format: "dd.mm.yyyy",
|
||||
language: 'de-DE',
|
||||
weekStart: 1,
|
||||
autoclose: true,
|
||||
todayHighlight: false});
|
||||
$('#datepickere').datepicker(
|
||||
{
|
||||
format: "dd.mm.yyyy",
|
||||
language: 'de-DE',
|
||||
weekStart: 1,
|
||||
autoclose: true,
|
||||
todayHighlight: false});
|
||||
</script>
|
||||
<script src="/js/tables.js"></script>
|
||||
<script src="/js/tab_accounts.js"></script>
|
||||
<script src="/js/activities.js"></script>
|
||||
|
||||
<script src="/js/tab_activities.js"></script>
|
||||
<?= $this->endSection(); ?>
|
||||
56
app/Views/bill_bookingline.php
Normal file
56
app/Views/bill_bookingline.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
if (!$template) {
|
||||
$parentList = $booking['cat_parent'][$i];
|
||||
$subList = $booking['cat_sub'][$i];
|
||||
$account_id = $booking['account_id'][$i];
|
||||
$parent_id = $booking['parent_id'][$i];
|
||||
$comment = $booking['comment'][$i];
|
||||
$input = $booking['input'][$i];
|
||||
$output = $booking['output'][$i];
|
||||
$sid = $booking['sid'][$i];
|
||||
} else {
|
||||
$i = 0;
|
||||
$account_id = 0;
|
||||
$parent_id = 0;
|
||||
$parentList = $booking['category']['parent'];
|
||||
$subList = $booking['category']['subs']->{$parent_id};
|
||||
$comment = '';
|
||||
$input = '';
|
||||
$output = '';
|
||||
$sid = 0;
|
||||
}
|
||||
?>
|
||||
|
||||
<div <?=(($template)?'id="template"':'')?> class="row <?=(($template)?'d-none':'')?>">
|
||||
<input type="hidden" value="<?= $sid ?>" name="sid[]">
|
||||
|
||||
<div class="col-lg-3 col-6 col-md-6 <?=(($i>0)?'multi':'')?> order-sm-2 px-0">
|
||||
<select name="parent_id[]" class="form-select parent" <?=(($i==0 && !$template)?'required':'')?>>
|
||||
<option value="">----</option>
|
||||
<?php foreach ($parentList as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == $parent_id)?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-lg-3 col-6 col-md-6 <?=(($i>0)?'multi':'')?> order-sm-2 px-0" <?=(($i==0 && !$template)?'required':'')?>>
|
||||
<select name="account_id[]" class="form-select sub">
|
||||
<?php foreach ($subList as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == $account_id && $account_id>0)?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="w-100 d-md-none"></div>
|
||||
<div class="col-lg-2 col-6 <?=(($i>0)?'multi':'')?> <?= ($booking['transfer']?' d-none':'') ?> px-0 order-sm-2">
|
||||
<input type="text" name="input[]" class="form-control dt-subamount input" placeholder="Einnahme" value="<?= $input ?>"
|
||||
pattern="[0-9\*\(\)\-\+\/,.]*"
|
||||
oninput="if (!this.checkValidity()) this.value = this.value.slice(0, -1)">
|
||||
</div>
|
||||
<div class="<?= ($booking['transfer']?'col-lg-4 col-12':'col-lg-2 col-6') ?> <?=(($i>0)?'multi':'')?> px-0 order-sm-2">
|
||||
<input type="text" name="output[]" placeholder="Ausgabe" value="<?= $output ?>"
|
||||
pattern="[0-9\*\(\)\-\+\/,.]*"
|
||||
oninput="if (!this.checkValidity()) this.value = this.value.slice(0, -1)" class="form-control dt-subamount output text-danger" >
|
||||
</div>
|
||||
<div class="col-lg-2 col-12 col-md-12 <?=(($i>0)?'multi':'')?> order-sm-1 px-0 mb-3 mb-md-0">
|
||||
<input type="text" name="comment[]" class="form-control" placeholder="Kommentar" value="<?= $comment ?>">
|
||||
</div>
|
||||
</div>
|
||||
19
app/Views/bill_scheduled.php
Normal file
19
app/Views/bill_scheduled.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<div class="col-12 scheduled <?=($booking['scheduled']?'':'d-none')?>">
|
||||
<div class="form-group">
|
||||
<label for="scheduledNum">Scheduled:</label>
|
||||
<div class="input-group">
|
||||
<select name="scheduledNum" id="scheduledNum" class="form-select" required>
|
||||
<option value="">----</option>
|
||||
<?php foreach ($booking['schedule_lists']['NumList'] as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == $booking['scheduledNum'])?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<select name="scheduledType" id="scheduledType" class="form-select" required>
|
||||
<option value="">----</option>
|
||||
<?php foreach ($booking['schedule_lists']['TypeList'] as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == $booking['scheduledType'])?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -8,18 +8,14 @@
|
||||
<meta name="description" content="Adminpage for Finanzen" />
|
||||
<meta name="author" content="Wimpissinger Markus" />
|
||||
<?= $this->renderSection('css_first') ?>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@300;400;600;700;800&display=swap" rel="stylesheet">
|
||||
<link href="/assets/bootstrap-5.3.0-alpha1-dist/css/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="/assets/fontawesome6.4.0/css/fontawesome.css" rel="stylesheet">
|
||||
<link href="/assets/fontawesome6.4.0/css/solid.css" rel="stylesheet">
|
||||
<link href="/assets/fontawesome6.4.0/css/brands.css" rel="stylesheet">
|
||||
<link href="/assets/fontawesome6.4.0/css/regular.css" rel="stylesheet">
|
||||
<!-- <link rel="stylesheet" href="/assets/vendors/perfect-scrollbar/perfect-scrollbar.css"> -->
|
||||
<link href="/assets/bootstrap/css/bootstrap.css" rel="stylesheet" />
|
||||
<link href="/assets/font-awesome/css/fontawesome.css" rel="stylesheet">
|
||||
<link href="/assets/font-awesome/css/solid.css" rel="stylesheet">
|
||||
<link href="/assets/font-awesome/css/brands.css" rel="stylesheet">
|
||||
<link href="/assets/font-awesome/css/regular.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/assets/css/app.css">
|
||||
<link href="/assets/DataTables/datatables.min.css" rel="stylesheet"/>
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" type="text/javascript"></script> -->
|
||||
<?= $this->renderSection('css') ?>
|
||||
<!-- <link rel="shortcut icon" href="/assets/images/favicon.svg" type="image/x-icon"> -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -34,20 +30,41 @@
|
||||
</a>
|
||||
</header>
|
||||
<?= $this->renderSection('content') ?>
|
||||
<div class="modal" id="mymodal" tabindex="-1">
|
||||
<div class="modal fade" id="mymodal" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header d-none">
|
||||
<h1 class="modal-title fs-5" id="modalTitle">Modal Title</h1>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5 class="modal-title"></h5>
|
||||
<p>Wirklich löschen?</p>
|
||||
<p>Modal body</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbruch</button>
|
||||
<button type="button" id="modal_ok" class="btn btn-primary">Löschen</button>
|
||||
<div class ="mx-auto">
|
||||
<button type="button" id="modal_ok" data-bs-dismiss="modal" class="btn btn-primary">Ok</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal" id="mymodalDelete" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title fs-5" id="modalDelTitle">Wirklich löschen?</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body d-none">
|
||||
<p class="modal-text">Wirklich löschen?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class ="mx-auto">
|
||||
<button type="button" id="modal_delete" class="btn btn-primary" data-bs-target="#mymodal" data-bs-toggle="modal">Löschen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="mySnycModal" tabindex="-1" aria-labelledby="Snc Result Window" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
@@ -82,16 +99,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <script src="/assets/vendors/perfect-scrollbar/perfect-scrollbar.min.js"></script>
|
||||
<script src="/assets/js/bootstrap.bundle.min.js"></script> -->
|
||||
<script src="/assets/jquery-3.6.4.min.js" type="text/javascript"></script>
|
||||
<script src="/assets/bootstrap-5.3.0-alpha1-dist/js/bootstrap.bundle.js" type="text/javascript"></script>
|
||||
<script defer src="/assets/fontawesome6.4.0/js/solid.js"></script>
|
||||
<script defer src="/assets/fontawesome6.4.0/js/brands.js"></script>
|
||||
<script defer src="/assets/fontawesome6.4.0/js/regular.js"></script>
|
||||
<script src="/assets/DataTables/datatables.min.js"></script>
|
||||
<!-- <script src="/assets/vendors/perfect-scrollbar/perfect-scrollbar.min.js"></script> -->
|
||||
<script src="/assets/bootstrap/js/bootstrap.bundle.js" type="text/javascript"></script>
|
||||
<script src="/assets/fiduswriter/simple-datatables.js" type="text/javascript"></script>
|
||||
<!-- <script defer src="/assets/fontawesome/js/solid.js"></script>
|
||||
<script defer src="/assets/fontawesome/js/brands.js"></script>
|
||||
<script defer src="/assets/fontawesome/js/regular.js"></script> -->
|
||||
<script src="/js/menue.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<?= $this->renderSection('scripts') ?>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
<div class="col-md-8 col-12">
|
||||
<div class="card">
|
||||
<div class="card-header pb-0">
|
||||
<?php if ($id) : ?>
|
||||
<h4 class="card-title"><?= ($transfer?'Transfer bearbeiten':($isScheduled?'Terminbuchung bearbeiten':'Rechnung bearbeiten'))?></h4>
|
||||
<?php if ($booking['id']) : ?>
|
||||
<h4 class="card-title"><?= ($booking['transfer']?'Transfer '.$booking['id'].' bearbeiten':($booking['scheduled']?'Terminbuchung '.$booking['id'].' bearbeiten':'Rechnung '.$booking['id'].' bearbeiten'))?></h4>
|
||||
<?php else: ?>
|
||||
<h4 class="card-title"><?= ($transfer?'Neuer Transfer':($isScheduled?'Neue Terminbuchung':'Neue Rechnung'))?></h4>
|
||||
<h4 class="card-title"><?= ($booking['transfer']?'Neuer Transfer':($booking['scheduled']?'Neue Terminbuchung':'Neue Rechnung'))?></h4>
|
||||
|
||||
<?php endif; ?>
|
||||
<?php if (! empty($validation)) : ?>
|
||||
@@ -34,27 +34,25 @@
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
<?= form_open_multipart('newBill','class="form form-vertical" onsubmit="logData(event)" id="newbill"') ?>
|
||||
<?= view("bill_bookingline",['booking'=>$booking, 'template'=>true]); ?>
|
||||
<form id="newbill" action="/edit" class="form form-vertical needs-validation" method="post" enctype="multipart/form-data" onsubmit="checkForm(event,this)" novalidate>
|
||||
<!-- <form class="form form-vertical" id="newbill" method="post" enctype="multipart/form-data" onsubmit="logData(event)" action="<?= base_url() ?>newBill"> -->
|
||||
<input type="hidden" value="<?= $id ?>" name="id">
|
||||
<input type="hidden" value="<?= $transfer?'1':'0' ?>" name="transfer">
|
||||
<input type="hidden" value="<?= $booking['id'] ?>" name="id">
|
||||
<input type="hidden" value="<?= $booking['amount']??0.0 ?>" name="amount">
|
||||
<input type="hidden" value="<?= $booking['transfer']?'1':'0' ?>" name="transfer">
|
||||
<input type="hidden" value="<?= ($booking['scheduled']??false)?'1':'0' ?>" name="scheduled">
|
||||
|
||||
<div class="form-body">
|
||||
<div class="row">
|
||||
<div class="col-12 <?= ($transfer?' d-none':'') ?>">
|
||||
<div class="form-check form-switch">
|
||||
<label class="form-check-label" for="multi">Multi Rechnung</label>
|
||||
<input class="form-check-input" type="checkbox" id="multi" value="on" name="multi" <?= set_checkbox('multi', 'on', $multi??false) ?>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 <?= ($transfer?' d-none':($isScheduled?' d-none':'')) ?>">
|
||||
<div class="col-12 <?= ($booking['transfer']?' d-none':(($booking['scheduled']??false)?' d-none':'')) ?>">
|
||||
<label for="billfile">Rechnung:</label>
|
||||
<input type="file" id="billfile" name="billfile" class="form-control <?= (!isset($billfile))?'':'d-none' ?>" capture="environment" accept="image/*, application/pdf">
|
||||
<?php if (isset($billfile)): ?>
|
||||
<a href="/viewBill/<?= $billfile ?>" id="billfileRef"><?= $billfile ?></a>
|
||||
<input type="file" id="billfile" name="billfile" class="form-control <?= (!isset($booking['rechnung']))?'':'d-none' ?>" capture="environment" accept="image/*, application/pdf">
|
||||
<?php if (isset($booking['rechnung'])): ?>
|
||||
<a href="/viewInvoice/<?= $booking['rechnung'] ?>" id="billfileRef" target="_blank"> <?= $booking['rechnung'] ?></a>
|
||||
<a class="" onclick="removeBillFile(this);"><i class="fa fa-trash"></i></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="col-12 <?= ($transfer?' d-none':'d-none') ?>">
|
||||
<div class="col-12 <?= ($booking['transfer']?' d-none':'d-none') ?>">
|
||||
<div class='form-check'>
|
||||
<div class="checkbox">
|
||||
<label for="renummer">Re-Nr.</label>
|
||||
@@ -64,76 +62,64 @@
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="datum">Datum</label>
|
||||
<input type="date" class="form-control" id="datum" name="datum" value="<?= $datum ?>" onclick="openBox(this);"/>
|
||||
<input type="date" class="form-control" id="datum" name="datum" value="<?= $booking['datum'] ?>" onclick="openBox(this);"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 <?= ($transfer?' d-none':'') ?>">
|
||||
<div class="col-12 <?= ($booking['transfer']?' d-none':'') ?>">
|
||||
<div class="form-group">
|
||||
<label for="receiver">Empfänger</label>
|
||||
<input type="text" class="form-control" id="receiver" name="receiver" value="<?= $receiver ?>">
|
||||
<input type="text" class="form-control" id="receiver" name="receiver" <?=(($booking['transfer'])?'':'required')?> value="<?= $booking['receiver'] ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<label for="source">Konto:</label>
|
||||
<?= form_dropdown('source', $sourcelist, $source,'id="source" class="form-select"'); ?>
|
||||
<label for="sourceID">Konto:</label>
|
||||
<select name="source_id" class="form-select" required id="sourceID" >
|
||||
<option value="">----</option>
|
||||
<?php foreach ($booking['sourcelist'] as $key => $value): ?>
|
||||
<option value="<?= $key ?>" <?= ($key == $booking['source_id'])?'selected':'' ?>><?= $value ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 multi">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control dt-amount" id="total_in" name="total_in" placeholder="Einnahme" maxlength=120 value="<?= $total_in ?>">
|
||||
<input type="text" class="form-control dt-amount text-danger" id="total_out" name="total_out" placeholder="Ausgabe" maxlength=120 value="<?= $total_out ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 scheduled <?=($isScheduled?'':'d-none')?>">
|
||||
<div class="form-group">
|
||||
<label for="scheduledNum">Scheduled:</label>
|
||||
<div class="input-group">
|
||||
<input type="hidden" value="<?= $isScheduled?'1':'0' ?>" name="scheduled">
|
||||
<?= form_dropdown("scheduledNum", $scheduled['NumList'], $scheduledNum,$scheduled['style']); ?>
|
||||
<?= form_dropdown("scheduledType",$scheduled['TypeList'], $scheduledType,$scheduled['style']); ?>
|
||||
</div>
|
||||
<div class="input-group has-validation">
|
||||
<input type="text" id="total_in" name="total_in" value="<?= $booking['total_in'] ?>"
|
||||
class="form-control dt-amount input"
|
||||
pattern="[0-9\*\(\)\-\+\/,.]*"
|
||||
oninput="if (!this.checkValidity()) this.value = this.value.slice(0, -1)"
|
||||
placeholder="Einnahme" maxlength=120 ">
|
||||
<input type="text" id="total_out" name="total_out" value="<?= $booking['total_out'] ?>"
|
||||
class="form-control dt-amount output text-danger"
|
||||
pattern="[0-9\*\(\)\-\+\/,.]*"
|
||||
oninput="if (!this.checkValidity()) this.value = this.value.slice(0, -1)"
|
||||
placeholder="Ausgabe" maxlength=120>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ($booking['scheduled']??false)
|
||||
echo view("bill_scheduled",['booking'=>$booking]);
|
||||
?>
|
||||
<div class="col-12 d-none multi">
|
||||
<div class="form-group">
|
||||
<label for="openamount">Offener Betrag:</label>
|
||||
<input type="text" class="form-control dt-amount" readonly="readonly" id="openamount" name="openamount">
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12" id="linecont">
|
||||
<?php for ($i=0;$i<10;$i++): ?>
|
||||
<div class="row <?= (($i<3 || $input[$i]>0 || $output[$i]>0)?'':' d-none')?>">
|
||||
<input type="hidden" value="<?= $sid[$i] ?>" name="sid[<?=$i?>]">
|
||||
|
||||
<div class="col-lg-3 col-6 col-md-6 <?=(($i>0)?'multi':'')?> order-sm-2 px-0">
|
||||
<?= form_dropdown("category_parent[$i]", $subsparent[$i], $category_parent[$i], 'class="form-select parent"'); ?>
|
||||
</div>
|
||||
<div class="col-lg-3 col-6 col-md-6 <?=(($i>0)?'multi':'')?> order-sm-2 px-0 sub">
|
||||
<?= form_dropdown("category[$i]", $subscategory[$i], $category[$i], 'class="form-select"'); ?>
|
||||
</div>
|
||||
<div class="w-100 d-md-none"></div>
|
||||
<div class="col-lg-2 col-6 <?=(($i>0)?'multi':'')?> <?= ($transfer?' d-none':'') ?> px-0 order-sm-2">
|
||||
<input type="text" name="input[<?=$i?>]" class="form-control dt-subamount" placeholder="Einnahme" value="<?= $input[$i] ?>">
|
||||
</div>
|
||||
<div class="<?= ($transfer?'col-lg-4 col-12':'col-lg-2 col-6') ?> <?=(($i>0)?'multi':'')?> px-0 order-sm-2">
|
||||
<input type="text" name="output[<?=$i?>]" class="form-control dt-subamount text-danger" placeholder="Ausgabe" value="<?= $output[$i] ?>">
|
||||
</div>
|
||||
<div class="col-lg-2 col-12 col-md-12 <?=(($i>0)?'multi':'')?> order-sm-1 px-0 mb-3 mb-md-0">
|
||||
<input type="text" name="comment[<?=$i?>]" class="form-control" placeholder="Kommentar" value="<?= $comment[$i] ?>">
|
||||
</div>
|
||||
</div>
|
||||
<?php endfor; ?>
|
||||
<?php $i = 0; foreach ($booking['sid'] as $_sid) :
|
||||
echo view("bill_bookingline",['booking'=>$booking, 'i'=>$i,'template'=>false]);
|
||||
?>
|
||||
<?php $i++; endforeach; ?>
|
||||
</div>
|
||||
<div class="col-12 d-flex" role="group">
|
||||
<a class="btn btn-info multi" onclick="addLine();" role="button">+ Zeile</a>
|
||||
<input type="checkbox" id="validate" name="validate" value="1" class='btn-check' autocomplete="off" <?= set_checkbox('validate', '1', (($validate??"f")=="t")?true:false) ?>>
|
||||
<a id="multiadd" class="btn btn-info <?= ($booking['transfer']?' d-none':'') ?>" onclick="addLine();" role="button">+ Zeile</a>
|
||||
<input type="checkbox" id="validate" name="validate" value="1" class='btn-check' autocomplete="off" <?= set_checkbox('validate', '1', ($booking['validate'])?true:false) ?>>
|
||||
<label class="btn btn-outline-danger" for="validate">Entwurf</label>
|
||||
<?php if ($id) : ?>
|
||||
<a class="btn btn-danger" data-bs-toggle="modal" data-bs-id="<?= $id ?>" data-bs-target="#mymodal"><i class="fa fa-trash"></i></a>
|
||||
<?php if ($booking['id']) : ?>
|
||||
<a class="btn btn-danger" data-bs-toggle="modal" data-bs-table="<?= ($booking['scheduled']??false)?'scheduled':'bill'?>" data-bs-id="<?= $booking['id'] ?>" data-bs-target="#mymodalDelete"><i class="fa fa-trash"></i></a>
|
||||
<?php endif; ?>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<a class="btn btn-secondary" onclick="history.back();" role="button"><i class="fa-solid fa-rotate-left"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -149,7 +135,7 @@
|
||||
function openBox(e) {
|
||||
e.showPicker();
|
||||
}
|
||||
subsdata = <?= $subsdata; ?>;
|
||||
subsdata = <?= json_encode($booking['category']['subs']) ?>;
|
||||
</script>
|
||||
<script src="/js/billing.js"></script>
|
||||
<?= $this->endSection(); ?>
|
||||
@@ -1,31 +1,29 @@
|
||||
<?= $this->extend('layout'); ?>
|
||||
|
||||
<?= $this->section('css'); ?>
|
||||
<link rel="stylesheet" href="/assets/jquery-ui-1.13.2.custom/jquery-ui.css">
|
||||
<link rel="stylesheet" href="/css/mawim.css">
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('menu'); ?>
|
||||
<?= $this->include('sidebar') ?>
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('content'); ?>
|
||||
<?php session()->set('redirect_url',base_url('show-passwords')); ?>
|
||||
<?php session()->set('redirect_url',base_url('viewScheduled')); ?>
|
||||
<div class="page-content">
|
||||
<div class="row">
|
||||
<div class="col-xxl-8 col-12">
|
||||
<div class="text-white-50"><h2>Terminbuchungen</h2></div>
|
||||
<table class="table table-striped table-sm" id="scheduled" cellspacing="0"></table>
|
||||
<table id="scheduled" cellspacing="0"></table>
|
||||
</div>
|
||||
<div class="col-xxl-4 col-12 d-none d-xxl-block">
|
||||
<div class="text-white-50"><h2>Aktuelle Kontostände</h2></div>
|
||||
<table class="table table-striped table-sm" id="accounts" cellspacing="0"></table>
|
||||
<table id="accounts" cellspacing="0"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?= $this->endSection(); ?>
|
||||
<?= $this->section('scripts'); ?>
|
||||
<script src="/assets/jquery-ui-1.13.2.custom/jquery-ui.js"></script>
|
||||
<script src="/js/tables.js"></script>
|
||||
<script src="/js/tab_accounts.js"></script>
|
||||
<script src="/js/scheduled.js"></script>
|
||||
<script src="/js/tab_scheduled.js"></script>
|
||||
|
||||
<?= $this->endSection(); ?>
|
||||
@@ -30,10 +30,10 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item active">
|
||||
<a href="javascript:syncScheduled()" class='sidebar-link'>
|
||||
<a class="sidebar-link" data-bs-toggle="modal" role="button" data-bs-target="#mySnycModal" onclick="syncScheduled(this)">
|
||||
<i class="fa-solid fa-pen-to-square"></i>
|
||||
<span>Sync Automatische</span>
|
||||
</a>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item active">
|
||||
<a href="/viewAccounts" class='sidebar-link'>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?= $this->extend('layout'); ?>
|
||||
<?= $this->extend('layout'); ?>
|
||||
|
||||
<?= $this->section('css'); ?>
|
||||
<link rel="stylesheet" href="/css/mawim.css">
|
||||
@@ -15,21 +15,21 @@
|
||||
<div class="col-xl-4 col-md-8 col-sm-12">
|
||||
<div class="text-white-50"><h2>Aktuelle Buchungen</h2></div>
|
||||
<div class="">
|
||||
<table class="table table-striped table-sm" id="bookings" cellspacing="0">
|
||||
<table id="bookings" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-8 col-sm-12">
|
||||
<div class="text-white-50"><h2>Aktuelle Kontostände</h2></div>
|
||||
<div class="">
|
||||
<table class="table table-striped table-sm" id="accounts" cellspacing="0">
|
||||
<table id="accounts" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-md-8 col-sm-12">
|
||||
<div class="text-white-50"><h2>Überfällige</h2></div>
|
||||
<div class="">
|
||||
<table class="table table-striped table-sm" id="todos" cellspacing="0">
|
||||
<table id="todos" cellspacing="0">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,6 +40,7 @@
|
||||
<?= $this->section('scripts'); ?>
|
||||
<script src="/js/tables.js"></script>
|
||||
<script src="/js/tab_accounts.js"></script>
|
||||
<script src="/js/tabs_overview.js"></script>
|
||||
|
||||
<script src="/js/tab_todos.js"></script>
|
||||
<script src="/js/tab_overview.js"></script>
|
||||
|
||||
<?= $this->endSection(); ?>
|
||||
@@ -918,7 +918,9 @@
|
||||
z-index: 10;
|
||||
overflow-y: auto;
|
||||
bottom: 0;
|
||||
background-color: var(--bs-body-bg);
|
||||
transition: left .5s ease-out
|
||||
|
||||
}
|
||||
|
||||
.sidebar-wrapper .sidebar-header {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
.dt-amount, .dt-subamount{
|
||||
text-align:right;
|
||||
}
|
||||
.invalid-feedback{
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
.dataTables_info{
|
||||
float:left;
|
||||
padding-top:0px !important;
|
||||
@@ -10,6 +14,19 @@
|
||||
float:left;
|
||||
}
|
||||
|
||||
.datatable-sorter {
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
border-color: inherit;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
font-weight:700;
|
||||
}
|
||||
.datatable-icon {
|
||||
padding-left:0 !important;
|
||||
padding-right:0 !important;
|
||||
}
|
||||
|
||||
.toolbar, .syncbutton{
|
||||
float:left;
|
||||
padding-left:10px;
|
||||
|
||||
@@ -1,67 +1,71 @@
|
||||
function newCat(){
|
||||
$('#editor').removeClass('d-none');
|
||||
$("#id").val(0);
|
||||
tree = document.getElementById('tree');
|
||||
editor = document.getElementById("editor");
|
||||
var elementTop = $('#editor').offset().top;
|
||||
var elementBottom = elementTop + $(this).outerHeight();
|
||||
|
||||
var viewportTop = $(window).scrollTop();
|
||||
var viewportBottom = viewportTop + $(window).height();
|
||||
|
||||
|
||||
if (!(elementBottom > viewportTop && elementTop < viewportBottom))
|
||||
editor.scrollIntoView( {behavior: "smooth" });
|
||||
function moveEditor(){
|
||||
treepos = 90 - document.getElementById("tree").getBoundingClientRect().top;
|
||||
editor.style.position = 'relative';
|
||||
editor.style.top = treepos+'px';
|
||||
}
|
||||
function scrollToEditor(){
|
||||
let editor = document.getElementById("editor");
|
||||
editor.scrollIntoView( {behavior: "smooth" });
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$('.tree li:has(ul)').addClass('parent_li').find(' > span');
|
||||
$('.tree li.parent_li > span').on('click', function (e) {
|
||||
var children = $(this).parent('li.parent_li').find(' > ul > li');
|
||||
if (children.is(":visible")) {
|
||||
children.hide('fast');
|
||||
// $(this).find(' > i').addClass('icon-plus-sign').removeClass('icon-minus-sign');
|
||||
} else {
|
||||
children.show('fast');
|
||||
// $(this).find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign');
|
||||
}
|
||||
e.stopPropagation();
|
||||
});
|
||||
$("span").on('click', function(e){
|
||||
$('#editor').removeClass('d-none');
|
||||
bookable = ($(this).attr('data-bookable') == "f")?false:true;
|
||||
lkz = ($(this).attr('data-lkz') == 0)?false:true;
|
||||
type = $(this).attr('data-type');
|
||||
pid = $(this).attr('data-pid');
|
||||
id = $(this).attr('data-id');
|
||||
description = $(this).attr('data-description');
|
||||
typeAccount = (type === "account") ? true : false;
|
||||
typeInput = (type === "input") ? true : false;
|
||||
typeOutput = (type === "output") ? true : false;
|
||||
$('#bookable').prop('checked', bookable);
|
||||
$('#typeInput').prop('checked', typeInput);
|
||||
$('#typeOutput').prop('checked', typeOutput);
|
||||
$('#typeAccount').prop('checked', typeAccount);
|
||||
$('#lkz').prop('checked', lkz);
|
||||
$("#parent").val(pid).change();
|
||||
$("#id").val(id);
|
||||
$("#description").val(description).change();
|
||||
tree = document.getElementById('tree');
|
||||
editor = document.getElementById("editor");
|
||||
var elementTop = $('#editor').offset().top;
|
||||
var elementBottom = elementTop + $(this).outerHeight();
|
||||
|
||||
var viewportTop = $(window).scrollTop();
|
||||
var viewportBottom = viewportTop + $(window).height();
|
||||
|
||||
|
||||
if (!(elementBottom > viewportTop && elementTop < viewportBottom))
|
||||
editor.scrollIntoView( {behavior: "smooth" });
|
||||
//$('#parent').prop('selected', pid);
|
||||
function newCat(){
|
||||
document.getElementById("editor").classList.remove("d-none");
|
||||
document.getElementById("id").value = 0;
|
||||
document.getElementById("bookable").checked = true;
|
||||
document.getElementById("account").checked = false;
|
||||
document.getElementById("monitor").checked = false;
|
||||
document.getElementById("deleted_at").checked = false;
|
||||
document.getElementById("parent").value = 0;
|
||||
document.getElementById("description").value = "";
|
||||
// scrollEditor();
|
||||
}
|
||||
|
||||
// title: "Edit Account",
|
||||
// placement: 'bottom',
|
||||
// html: true,
|
||||
// content: $('[data-name="popover-content"]')
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
editor = document.getElementById("editor");
|
||||
document.querySelectorAll('.tree li:has(ul)').forEach((single) => {
|
||||
single.classList.add("parent_li");
|
||||
single.getElementsByTagName("i")[0].classList.add("fa-square-minus");
|
||||
});
|
||||
document.querySelectorAll(".tree span").forEach((spa) => {
|
||||
spa.addEventListener("dblclick", (event) => {
|
||||
const viewportWidth = document.documentElement.clientWidth;
|
||||
if (viewportWidth < 768)
|
||||
scrollToEditor();
|
||||
else
|
||||
moveEditor();
|
||||
|
||||
editor.classList.remove("d-none");
|
||||
|
||||
document.getElementById("bookable").checked = event.target.getAttribute("data-bookable")=="true";
|
||||
document.getElementById("account").checked = event.target.getAttribute("data-account")=="true";
|
||||
document.getElementById("monitor").checked = event.target.getAttribute("data-monitor")=="true";
|
||||
document.getElementById("deleted_at").checked = event.target.getAttribute("data-deleted")!== "";
|
||||
document.getElementById("id").value = event.target.getAttribute("data-id");
|
||||
document.getElementById("parent").value = event.target.getAttribute("data-pid");
|
||||
document.getElementById("description").value = event.target.getAttribute("data-description");
|
||||
// scrollEditor();
|
||||
});
|
||||
});
|
||||
document.querySelectorAll('.tree li.parent_li > span, .tree li.parent_li > i').forEach((parent) => {
|
||||
parent.addEventListener("click",(event) => {
|
||||
let single = event.target.parentElement.querySelector('ul,li');
|
||||
let visible = single.classList.toggle("d-none");
|
||||
if (visible) {
|
||||
event.target.parentElement.querySelector("i").classList.add("fa-square-plus");
|
||||
event.target.parentElement.querySelector("i").classList.remove("fa-square-minus");
|
||||
} else {
|
||||
event.target.parentElement.querySelector("i").classList.add("fa-square-minus");
|
||||
event.target.parentElement.querySelector("i").classList.remove("fa-square-plus");
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
document.getElementById("viewdeleted").addEventListener("click",(event) => {
|
||||
document.querySelectorAll(".tree span").forEach((spa) => {
|
||||
if (event.currentTarget.checked && spa.getAttribute("data-deleted")!== "")
|
||||
spa.parentElement.classList.remove("d-none");
|
||||
else if ((!event.currentTarget.checked) && spa.getAttribute("data-deleted")!== "")
|
||||
spa.parentElement.classList.add("d-none");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,57 +0,0 @@
|
||||
var datatable;
|
||||
var colomnspez = columns;
|
||||
function createSearchData(data, type, row){
|
||||
let details = "";
|
||||
data.forEach(function(item){
|
||||
details += item.comment+' '+item.description+' ';
|
||||
details += new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(item.subamount);
|
||||
});
|
||||
return details;
|
||||
}
|
||||
|
||||
colomnspez.splice(3, 0, { title: "Quelle",orderable:false, data: "source",className:"dt-source" });
|
||||
colomnspez.splice(6, 0, { title: "Details",orderable:false, visible:false, searchable:true, data: "details",className:"",render: createSearchData});
|
||||
$(document).ready(function(){
|
||||
datatable = $('#bookings').DataTable({
|
||||
paging: false,
|
||||
searching:true,
|
||||
scrollX:false,
|
||||
info:false,
|
||||
order: [[ 1, 'desc' ],[ 0, 'desc' ]],
|
||||
"processing": true,
|
||||
ajax: {
|
||||
type : 'POST',
|
||||
url : '/Ajax/getTabelData',
|
||||
data : function(d){
|
||||
d.datum_start = $('#datepickers').val();
|
||||
d.datum_ende = $('#datepickere').val();
|
||||
d.source = $('#source').val();
|
||||
},
|
||||
dataSrc:''},
|
||||
layout: {
|
||||
topStart: {
|
||||
buttons: [
|
||||
{text:'Neue Rechnung',className:'btn-sm',action: function ( e, dt, node, config ) {
|
||||
location.href = '/newBill/';
|
||||
}},
|
||||
{text:'Neuer Transfer',className:'btn-sm mx-2',action: function ( e, dt, node, config ) {
|
||||
location.href = '/newTransfer/';
|
||||
}},
|
||||
]
|
||||
},
|
||||
topEnd: 'search'
|
||||
},
|
||||
// dom: '<"toolbar">frt',
|
||||
"createdRow": function ( row, data, index ) {
|
||||
if(data.validate == "t"){
|
||||
$(row).addClass('text-bg-warning');
|
||||
}
|
||||
},
|
||||
columns: colomnspez,
|
||||
});
|
||||
|
||||
// $("div.toolbar").html('<a class="btn-sm btn-secondary mx-2" href="/newBill" role="button">Neue Rechnung</a><a class="btn-sm btn-secondary" href="/newTransfer" role="button">Neuer Transfer</a>');
|
||||
$('#bookings tbody').on('click', 'td.dt-receiver', function () {collapseDetails($(this), datatable);} );
|
||||
$('#bookings tbody').on('click', 'td.dt-datum', function () {location.href = '/editBill/'+getId($(this),datatable);});
|
||||
$('#bookings tbody').on('click', 'table.tabdet', function () {location.href = '/editBill/'+$(this).attr('data-bs-id');});
|
||||
});
|
||||
@@ -1,35 +1,146 @@
|
||||
$(function () {
|
||||
$('.parent').change(function () {
|
||||
var $subs = $(this).parent().parent().children(".sub").children();
|
||||
$subs.children().remove().end();
|
||||
var $output = '';
|
||||
$liste = subsdata[$(this).val()];
|
||||
$sort = Object.entries($liste).sort((a, b) => (a[1] > b[1]) ? 1 : (b[1] > a[1]) ? -1 : 0);
|
||||
$.each($sort, function (key, value) {
|
||||
$output += '<option value="' + value[0] + '">' + value[1] + '</option>';
|
||||
});
|
||||
$subs.append($output);
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
document.myModal = document.getElementById('mymodal');
|
||||
document.myModalDelete = document.getElementById('mymodalDelete');
|
||||
document.myModalDelete.addEventListener('show.bs.modal', function (event) {
|
||||
var button = event.relatedTarget;
|
||||
var id = button.getAttribute('data-bs-id');
|
||||
var tab = button.getAttribute('data-bs-table');
|
||||
document.myModalDelete.setAttribute('data-bs-id',id);
|
||||
document.myModalDelete.setAttribute('data-bs-table',tab);
|
||||
});
|
||||
document.myModal.addEventListener('show.bs.modal', function (event) {
|
||||
var button = event.relatedTarget;
|
||||
var id = button.getAttribute('data-bs-id');
|
||||
var tab = button.getAttribute('data-bs-table');
|
||||
document.myModal.setAttribute('data-bs-id',id);
|
||||
document.myModal.setAttribute('data-bs-table',tab);
|
||||
});
|
||||
$('#multi').change(function () {
|
||||
if ($(this).is(":checked")) {
|
||||
$('.single').addClass('d-none');
|
||||
$('.multi').removeClass('d-none');
|
||||
return;
|
||||
}
|
||||
$('.single').removeClass('d-none');
|
||||
$('.multi').addClass('d-none');
|
||||
//'unchecked' event code
|
||||
}).change();
|
||||
$('.dt-amount, .dt-subamount').change(function () {
|
||||
var temp = convertInput($(this).val());
|
||||
$(this).val(convertOutput(temp));
|
||||
if ($('#multi').is(":checked")) {
|
||||
recalcOpenAmount();
|
||||
}
|
||||
}).change();
|
||||
|
||||
document.getElementById('modal_delete').addEventListener('click', deleteEntry );
|
||||
|
||||
|
||||
var event = new Event('change');
|
||||
|
||||
switchMulti();
|
||||
// dropdown elemente anpassen wenn parent sich ändert
|
||||
document.querySelectorAll(".parent").forEach((papa) => {
|
||||
papa.addEventListener("change", hdlDropDownChange);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".dt-amount.input,.dt-amount.output , .dt-subamount").forEach((amount) => {
|
||||
amount.addEventListener("change", hdlAmountChange);
|
||||
amount.dispatchEvent(event);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".dt-amount.input,.dt-amount.output,.dt-subamount, .parent").forEach((amount) => {
|
||||
amount.addEventListener("focus", hdlValidityStateLine);
|
||||
});
|
||||
|
||||
const form = document.getElementById('newbill');
|
||||
form.addEventListener('formdata', function(event) {
|
||||
const formData = event.formData;
|
||||
formData.set('validate', formData.has('validate') ? '1' : '0');
|
||||
// console.log(formData);
|
||||
});
|
||||
});
|
||||
|
||||
function loadPage(ev){
|
||||
let url = ev.relatedTarget.getAttribute('url');
|
||||
window.location.href="url";
|
||||
}
|
||||
|
||||
function switchMulti(){
|
||||
//const multi = document.getElementById("multi");
|
||||
if (document.getElementById("linecont").childElementCount>1) {
|
||||
document.getElementById("multiadd").text = "+Zeile";
|
||||
const singles = document.querySelectorAll(".single").forEach((single) => {
|
||||
single.classList.add("d-none");
|
||||
});
|
||||
const multis = document.querySelectorAll(".multi").forEach((multi) => {
|
||||
multi.classList.remove("d-none");
|
||||
});
|
||||
// addLine();
|
||||
} else {
|
||||
document.getElementById("multiadd").text = "Multi";
|
||||
const singles = document.querySelectorAll(".single").forEach((single) => {
|
||||
single.classList.remove("d-none");
|
||||
});
|
||||
const multis = document.querySelectorAll(".multi").forEach((ele) => {
|
||||
ele.classList.add("d-none");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function recalcRow(einnahme, ausgabe){
|
||||
let value = einnahme.value - ausgabe.value;
|
||||
|
||||
if (value < 0) {
|
||||
ausgabe.value = convertOutput(value *(-1));
|
||||
einnahme.value = '';
|
||||
} else {
|
||||
einnahme.value = convertOutput(value);
|
||||
ausgabe.value = '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function hdlAmountChange(event) {
|
||||
var temp = convertInput(event.target.value);
|
||||
event.target.value = convertOutput(temp);
|
||||
|
||||
let zeile = event.target.parentElement.parentElement;
|
||||
var einnahme = zeile.querySelector(".input");
|
||||
var ausgabe = zeile.querySelector(".output");
|
||||
|
||||
if (event.target.classList.contains("input")) {
|
||||
if ( ausgabe.value !== '')
|
||||
recalcRow(einnahme,ausgabe);
|
||||
}else {
|
||||
if ( einnahme.value !== '')
|
||||
recalcRow(einnahme, ausgabe);
|
||||
}
|
||||
|
||||
calcAmount();
|
||||
if (document.getElementById("linecont").childElementCount>1) {
|
||||
recalcOpenAmount();
|
||||
}
|
||||
}
|
||||
|
||||
function hdlDropDownChange(event) {
|
||||
var $sub = event.target.parentElement.parentElement.querySelector(".sub");
|
||||
while ($sub.options.length) {
|
||||
$sub.remove(0);
|
||||
}
|
||||
var output = '';
|
||||
var liste = subsdata[(event.target.value=="")?0:event.target.value];
|
||||
var sort = Object.entries(liste).sort((a, b) => (a[1] > b[1]) ? 1 : (b[1] > a[1]) ? -1 : 0);
|
||||
sort.forEach((value) => {
|
||||
output += '<option value="' + value[0] + '">' + value[1] + '</option>';
|
||||
});
|
||||
$sub.innerHTML = output;
|
||||
}
|
||||
|
||||
function hdlValidityState(ev){
|
||||
form = document.getElementById("newbill");
|
||||
this.classList.remove("is-invalid");
|
||||
this.setCustomValidity("");
|
||||
form.classList.remove('was-validated');
|
||||
}
|
||||
|
||||
function hdlValidityStateLine(ev){
|
||||
let form = document.getElementById("newbill");
|
||||
if (form.classList.contains('was-validated')) {
|
||||
//ev.target.parentNode.parentNode
|
||||
//document.getElementById("linecont").
|
||||
form.querySelectorAll(".dt-amount, .dt-subamount, .parent, .sub").forEach((amount) => {
|
||||
amount.setCustomValidity("");
|
||||
amount.classList.remove("is-invalid");
|
||||
amount.classList.remove("is-valid");
|
||||
});
|
||||
form.classList.remove('was-validated');
|
||||
}
|
||||
}
|
||||
|
||||
function logData(event) {
|
||||
var data = document.getElementById("billfile");
|
||||
console.log(data.value);
|
||||
@@ -37,12 +148,21 @@ function logData(event) {
|
||||
}
|
||||
|
||||
function addLine() {
|
||||
$('#linecont > div').each(function () {
|
||||
if ($(this).hasClass("d-none")) {
|
||||
$(this).removeClass("d-none");
|
||||
return false;
|
||||
}
|
||||
//let ele =document.querySelector("#linecont > div:last-child");
|
||||
var clonedDiv = document.getElementById("template").cloneNode(true);
|
||||
clonedDiv.removeAttribute("id");
|
||||
clonedDiv.classList.remove("d-none");
|
||||
clonedDiv.querySelector(".parent").addEventListener("change", hdlDropDownChange);
|
||||
clonedDiv.querySelectorAll(".dt-subamount").forEach((amount) => {
|
||||
amount.addEventListener("change", hdlAmountChange);
|
||||
});
|
||||
clonedDiv.querySelectorAll(".dt-subamount, .parent").forEach((amount) => {
|
||||
amount.addEventListener("focus", hdlValidityStateLine);
|
||||
});
|
||||
document.getElementById("linecont").appendChild(clonedDiv);
|
||||
if (document.getElementById("linecont").childElementCount==2){
|
||||
switchMulti();
|
||||
}
|
||||
}
|
||||
|
||||
function removeBillFile(e) {
|
||||
@@ -79,23 +199,97 @@ function convertOutput(number) {
|
||||
return "";
|
||||
}
|
||||
|
||||
function recalcOpenAmount() {
|
||||
var summe = 0.0;
|
||||
$('.dt-subamount').each(function () {
|
||||
b = $(this).val();
|
||||
b = convertInput(b);
|
||||
function calcAmount() {
|
||||
//let amount = convertInput(document.getElementsByName("amount")[0].value);
|
||||
let amount = 0.0;
|
||||
document.querySelectorAll(".dt-subamount").forEach((subamount) => {
|
||||
var b = convertInput(subamount.value);
|
||||
if (typeof b !== 'undefined') {
|
||||
b = $(this).hasClass("text-danger") ? b * (-1) : b;
|
||||
summe = summe + b;
|
||||
b = subamount.classList.contains("output") ? b * (-1) : b;
|
||||
amount = amount + b;
|
||||
}
|
||||
// summe = summe + convertInput($(this).val());
|
||||
});
|
||||
document.getElementsByName("amount")[0].value = convertOutput(amount);
|
||||
|
||||
$('#openamount').val(Math.round(($('#total_in').val() - $('#total_out').val() - summe) * 100) / 100);
|
||||
}
|
||||
|
||||
// $('form').submit(function () {
|
||||
// alert("disable elements");
|
||||
// $( ".d-none" ).prop( "disabled", true );
|
||||
// return true;
|
||||
// });
|
||||
function recalcOpenAmount() {
|
||||
form = document.getElementById('newbill');
|
||||
let summe = convertInput(document.getElementsByName("amount")[0].value);
|
||||
console.log("Re calculating open amount");
|
||||
var total_in = convertInput(document.getElementById("total_in").value || "0.0");
|
||||
var total_out = convertInput(document.getElementById("total_out").value || "0.0");
|
||||
|
||||
let val = convertOutput(Math.round((total_in - total_out - summe) * 100) / 100);
|
||||
if (parseFloat(val) !== 0.0){
|
||||
setValState(form.openamount,"Muss 0 sein");
|
||||
} else {
|
||||
setValState(form.openamount,"Muss 0 sein",true);
|
||||
}
|
||||
|
||||
document.getElementById("openamount").value = val;
|
||||
}
|
||||
|
||||
function setValState(ele, message,valid=false){
|
||||
if (valid){
|
||||
ele.classList.add("is-valid");
|
||||
ele.classList.remove("is-invalid");
|
||||
ele.setCustomValidity("");
|
||||
} else {
|
||||
ele.classList.add("is-invalid");
|
||||
ele.classList.remove("is-valid");
|
||||
ele.setCustomValidity(message);
|
||||
}
|
||||
}
|
||||
|
||||
function checkForm(e,form) {
|
||||
const subinputs = form.elements;
|
||||
|
||||
//for new transfer
|
||||
if (form.receiver.value =='' && form.transfer.value)
|
||||
form.receiver.value = subinputs['parent_id[]'].selectedOptions[0].text+"-"+subinputs['account_id[]'].selectedOptions[0].text;
|
||||
if (!form.total_in.parentElement.parentElement.classList.contains("d-none")) {
|
||||
//Gesamtbetrag fehlt
|
||||
if ((form.total_in.value == "" ) && (form.total_out.value == "")) {
|
||||
if (parseFloat(form.amount.value) > 0.0){
|
||||
setValState(form.total_in, "Notwendig");
|
||||
} else {
|
||||
setValState(form.total_out, "Notwendig");
|
||||
}
|
||||
}
|
||||
//Restbetrag
|
||||
if (parseFloat(form.openamount.value) !== 0.0){
|
||||
setValState(form.openamount, "Offener Betrag!");
|
||||
form.openamount.readOnly = false;
|
||||
}else{
|
||||
setValState(form.openamount, "Offener Betrag!",true);
|
||||
}
|
||||
subinputs['account_id[]'].forEach((line,index) => {
|
||||
//wenn Kategorie gewählt muss Betrag da sein
|
||||
if (line.value > 0){
|
||||
if (!((parseFloat(subinputs['output[]'][index].value) > 0.0) || (parseFloat(subinputs['input[]'][index].value) > 0.0))){
|
||||
setValState(subinputs['output[]'][index],"Notwendig");
|
||||
setValState(subinputs['input[]'][index],"Notwendig");
|
||||
} else {
|
||||
setValState(subinputs['output[]'][index],"Notwendig",true);
|
||||
setValState(subinputs['input[]'][index],"Notwendig",true);
|
||||
}
|
||||
}
|
||||
else if ((subinputs['output[]'][index].value !=="") || (subinputs['input[]'][index].value !=="")){
|
||||
setValState(line,"Notwendig");
|
||||
setValState(subinputs['parent_id[]'][index],"Notwendig");
|
||||
}
|
||||
else {
|
||||
setValState(line,"Notwendig",true);
|
||||
setValState(subinputs['parent_id[]'][index],"Notwendig",true);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!form.checkValidity()) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
form.openamount.readOnly = true;
|
||||
}
|
||||
form.classList.add('was-validated');
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,66 @@
|
||||
function syncScheduled(){
|
||||
$('#mySnycModal').modal('show');
|
||||
$('#mySnycModal').find('.modal-title').html("Synchronisierte Einträge!");
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "/syncScheduled/",
|
||||
data: {}, // serializes the form's elements.
|
||||
success: function(data){
|
||||
const myModale = document.querySelector('#mySnycModal');
|
||||
var modalText = myModale.querySelector('.modal-body');
|
||||
var modalFenster = myModale.querySelector('.modal-dialog');
|
||||
modalText.innerHTML = data;
|
||||
$('#todos').DataTable().ajax.reload();
|
||||
},
|
||||
error: function(data){
|
||||
const myModale = document.querySelector('#mySnycModal');
|
||||
var modalText = myModale.querySelector('.modal-body');
|
||||
var modalFenster = myModale.querySelector('.modal-dialog');
|
||||
modalFenster.classList.add("alert");
|
||||
modalFenster.classList.add("alert-danger");
|
||||
modalText.textContent = 'Fehler bei der Ausführung!';
|
||||
$('#todos').DataTable().ajax.reload();
|
||||
function syncScheduled(ele){
|
||||
var myModal = document.getElementById('mySnycModal');
|
||||
var modalTitle = myModal.querySelector('.modal-title');
|
||||
let modalBody = myModal.querySelector('.modal-body');
|
||||
modalTitle.textContent = 'Synchronisierte Einträge!';
|
||||
modalBody.textContent = 'Please Wait!';
|
||||
fetch("/syncScheduled", { method: "GET",headers: {"X-Requested-With": "XMLHttpRequest"},})
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
const myModale = document.querySelector('#mySnycModal');
|
||||
var modalBody = myModale.querySelector('.modal-body');
|
||||
if (data === "") {
|
||||
modalBody.innerHTML = "Nix Neues Synchronisiert!";
|
||||
}
|
||||
});
|
||||
// location.href = '/syncScheduled/';
|
||||
else
|
||||
modalBody.innerHTML = data;
|
||||
if (typeof loadToDosData === "function")
|
||||
loadToDosData();
|
||||
})
|
||||
.catch(
|
||||
error => {
|
||||
const myModale = document.querySelector('#mySnycModal');
|
||||
var modalBody = myModale.querySelector('.modal-body');
|
||||
modalBody.innerHTML = "Fehler bei der Ausführung! " + error;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function deleteEntry(event) {
|
||||
let myModalDelete = document.getElementById('mymodalDelete');
|
||||
let id = myModalDelete.getAttribute('data-bs-id');
|
||||
let table = myModalDelete.getAttribute('data-bs-table');
|
||||
let formData = new FormData();
|
||||
formData.set('id',id);
|
||||
|
||||
if (table == "scheduled")
|
||||
cmnd = "/deleteScheduled";
|
||||
else
|
||||
cmnd = "/deleteBill";
|
||||
fetch(cmnd, { method: "POST",headers: {"X-Requested-With": "XMLHttpRequest"}, body: formData})
|
||||
.then(response => {
|
||||
let myModal = document.getElementById('mymodal');
|
||||
let body = myModal.querySelector('.modal-body');
|
||||
if (!response.ok){
|
||||
body.innerHTML = response.statusText;
|
||||
}
|
||||
else{
|
||||
myModal.addEventListener('hidden.bs.modal', event => {
|
||||
let url = event.target.getAttribute('data-bs-url');
|
||||
window.location.href= url;
|
||||
})
|
||||
//document.getElementById('modal_ok').addEventListener('click', loadPage );
|
||||
response.json().then(json => {
|
||||
console.log(json);
|
||||
myModal.setAttribute('data-bs-url',json.url);
|
||||
body.innerHTML = "Erfolgreich gelöscht " + json.ID;
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(
|
||||
error => {
|
||||
let body = myModal.querySelector('.modal-body');
|
||||
body.innerHTML = "Fehler bei der Ausführung! " + error;
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
var datatable;
|
||||
var columnspez = columns;
|
||||
columnspez.splice(3, 0, { title: "Quelle",orderable:false, data: "source",className:"dt-source" });
|
||||
|
||||
$(document).ready(function(){
|
||||
datatable = $('#scheduled').DataTable({
|
||||
paging: false,
|
||||
searching:true,
|
||||
scrollX:false,
|
||||
info:false,
|
||||
order: [[ 1, 'asc' ]],
|
||||
ajax: {url: '/Ajax/getScheduledData',dataSrc:''},
|
||||
layout: {
|
||||
topStart: {
|
||||
buttons: [
|
||||
{text:'Neue Rechnung',className:'btn-sm',action: function ( e, dt, node, config ) {
|
||||
location.href = '/newScheduled';
|
||||
}},
|
||||
{text:'Neuer Transfer',className:'btn-sm mx-2',action: function ( e, dt, node, config ) {
|
||||
location.href = '/newScheduledTransfer';
|
||||
}},
|
||||
]
|
||||
},
|
||||
topEnd: 'search'
|
||||
},
|
||||
columns: columnspez
|
||||
});
|
||||
|
||||
$('#scheduled tbody').on('click', 'td.dt-receiver', function () {collapseDetails($(this), datatable);} );
|
||||
$('#scheduled tbody').on('click', 'td.dt-datum', function () {location.href = '/editScheduled/'+getId($(this),datatable);});
|
||||
$('#scheduled tbody').on('click', 'table.tabdet', function () {location.href = '/editScheduled/'+$(this).attr('data-bs-id');});
|
||||
});
|
||||
@@ -1,16 +1,59 @@
|
||||
var accounts;
|
||||
$(document).ready(function(){
|
||||
accounts = $('#accounts').DataTable({
|
||||
var accountsdata;
|
||||
|
||||
function loadAccountsData(){
|
||||
document.accounts.setMessage("Loading Data");
|
||||
let status;
|
||||
fetch("/getAccountsBalance", { method: "GET",headers: {"X-Requested-With": "XMLHttpRequest"},})
|
||||
.then(response => {
|
||||
status = response.statusText;
|
||||
if (!response.ok) {
|
||||
throw "HTTP error: " + response.status + "; " + status;
|
||||
} else
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (document.accounts.hasRows){
|
||||
document.accounts.data.data.splice(0,document.accounts.data.data.length);
|
||||
document.accounts.hasRows = false;
|
||||
}
|
||||
document.accounts.insert({data:data.map(item => [item.description,item.amount])});
|
||||
document.accounts.update(true);
|
||||
})
|
||||
.catch(err => {
|
||||
document.accounts.setMessage(err);
|
||||
});
|
||||
}
|
||||
|
||||
function createDtAccounts(){
|
||||
document.accounts = new simpleDatatables.DataTable("#accounts", {
|
||||
searchable: false,
|
||||
paging: false,
|
||||
searching:true,
|
||||
scrollX:false,
|
||||
info:false,
|
||||
ajax: { url: '/Ajax/getAccountsBalance', dataSrc:''},
|
||||
layout: { topEnd: 'search' },
|
||||
// dom: '<"toolbar">frtip',
|
||||
data: {
|
||||
headings: ["Konto","Betrag"],
|
||||
data: accountsdata,
|
||||
},
|
||||
classes: {
|
||||
active: "active",
|
||||
disabled: "disabled",
|
||||
table: "table table-striped table-sm",
|
||||
},
|
||||
columns: [
|
||||
{ title: "Konto",orderable:false, data: "description",className:"dt-receiver" },
|
||||
colBetrag
|
||||
]
|
||||
{
|
||||
select:0,
|
||||
type: 'string',
|
||||
cellClass:"dt-receiver",
|
||||
},{
|
||||
select:1,
|
||||
type: 'number',
|
||||
headerClass: "dt-amount",
|
||||
cellClass:"dt-amount",
|
||||
render: renderAmount
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
loadAccountsData();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
createDtAccounts();
|
||||
});
|
||||
111
public/js/tab_activities.js
Normal file
111
public/js/tab_activities.js
Normal file
@@ -0,0 +1,111 @@
|
||||
var activitydata;
|
||||
var colomnspez = columns;
|
||||
|
||||
function loadActivityData(){
|
||||
document.activities.setMessage("Loading Data");
|
||||
const form = document.querySelector("#getData");
|
||||
let formData = new FormData(form);
|
||||
// formData.append('start', document.getElementById("datum_start").value);
|
||||
// formData.append('end', document.getElementById("datum_ende").value);
|
||||
// formData.append('source', document.getElementById("source").value);
|
||||
fetch("/getActivitiesData", { method: "POST",headers: {"X-Requested-With": "XMLHttpRequest"}, body: formData })
|
||||
.then(response => {
|
||||
let status = response.statusText;
|
||||
if (!response.ok) {
|
||||
throw "HTTP error: " + response.status + "; " + status;
|
||||
} else
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (document.activities.hasRows){
|
||||
document.activities.data.data.splice(0,document.activities.data.data.length);
|
||||
document.activities.hasRows = false;
|
||||
}
|
||||
//document.activities.insert({data:data});
|
||||
document.activities.insert({data:data.map(item => [item.id,item.datum,item.receiver,item.source,item.amount,item.validate])});
|
||||
document.activities.update(true);
|
||||
})
|
||||
.catch(err => {
|
||||
document.activities.setMessage(err);
|
||||
});
|
||||
}
|
||||
|
||||
function createDtActivities(){
|
||||
document.activities = new simpleDatatables.DataTable("#activities", {
|
||||
searchable: true,
|
||||
paging: false,
|
||||
classes: {
|
||||
active: "active",
|
||||
disabled: "disabled",
|
||||
table: "table table-striped table-sm",
|
||||
},
|
||||
data: {
|
||||
headings: ["","Datum","Empfänger",,"Quelle","Betrag","draft"],
|
||||
data: activitydata,
|
||||
},
|
||||
rowRender: (row, tr, _index) => {
|
||||
//tr.childNodes[1].childNodes[0].attributes.href = `editBill/${row.cells[0].data}`;
|
||||
tr.childNodes[1].attributes.onclick = `location.href='editBill/${row.cells[0].data}'`;
|
||||
if(row.cells[5].data == true){
|
||||
tr.attributes.class = 'text-bg-warning';
|
||||
}
|
||||
// $(row).addClass('text-bg-warning');
|
||||
// tr.childNodes[2].attributes.onclick = `collapseDetails(this, ${_index})`;
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
select:0,
|
||||
render: (data, _cell, _dataIndex, _cellIndex) => { return `<a data-bs-toggle="modal" role="button" data-bs-id="${data}" data-bs-target="#mymodalDelete" ><i class="fa-solid fa-trash"></a>` },
|
||||
cellClass: "datatable-icon",
|
||||
type: "number",
|
||||
},{
|
||||
select:1,
|
||||
type: 'date',
|
||||
format: 'dd.mm.yyyy',
|
||||
cellClass:"dt-datum",
|
||||
sortable: true,
|
||||
sort: "desc",
|
||||
},{
|
||||
select:2,
|
||||
type: 'string',
|
||||
cellClass:"dt-receiver",
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a onclick="collapseDetails(this,document.bookings)">${data}</a>` },
|
||||
|
||||
},{
|
||||
select:3,
|
||||
type: 'string',
|
||||
cellClass:"dt-source",
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a onclick="collapseDetails(this,document.bookings)">${data}</a>` },
|
||||
|
||||
},{
|
||||
select:4,
|
||||
type: 'number',
|
||||
headerClass: "dt-amount",
|
||||
cellClass:"dt-amount",
|
||||
render: renderAmount
|
||||
},{
|
||||
select:5,
|
||||
type: 'boolean',
|
||||
hidden:true,
|
||||
}
|
||||
|
||||
],
|
||||
template: (options, dom) => `<div class='${options.classes.top}'>
|
||||
<div class='float-start'>
|
||||
<a class="btn btn-sm btn-secondary" href="newBill">Neue Rechnung</a>
|
||||
<a class="btn btn-sm btn-secondary" href="newTransfer">Neuer Transfer</a>
|
||||
</div>
|
||||
<div class='${options.classes.search} float-end'>
|
||||
<input class='${options.classes.input}' placeholder='Search' type='search' title='${options.labels.searchTitle}'${dom.id ? ` aria-controls="${dom.id}"` : ""}>
|
||||
</div>
|
||||
</div>
|
||||
<div class='${options.classes.container}'${options.scrollY.length ? ` style='height: ${options.scrollY}; overflow-Y: auto;'` : ""}></div>
|
||||
<div class='${options.classes.bottom}'>
|
||||
</div>`
|
||||
});
|
||||
loadActivityData();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
createDtActivities();
|
||||
});
|
||||
88
public/js/tab_overview.js
Normal file
88
public/js/tab_overview.js
Normal file
@@ -0,0 +1,88 @@
|
||||
var bookingdata;
|
||||
|
||||
function createDtOverviewBookings(){
|
||||
document.bookings = new simpleDatatables.DataTable("#bookings", {
|
||||
searchable: false,
|
||||
paging: false,
|
||||
data: {
|
||||
headings: ["","Datum","Empfänger","Betrag"],
|
||||
data: bookingdata,
|
||||
},
|
||||
rowRender: (row, tr, _index) => {
|
||||
//tr.childNodes[1].childNodes[0].attributes.href = `editBill/${row.cells[0].data}`;
|
||||
tr.childNodes[1].attributes.onclick = `location.href='editBill/${row.cells[0].data}'`;
|
||||
// tr.childNodes[2].attributes.onclick = `collapseDetails(this, ${_index})`;
|
||||
},
|
||||
classes: {
|
||||
active: "active",
|
||||
disabled: "disabled",
|
||||
table: "table table-striped table-sm",
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
select:0,
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a data-bs-toggle="modal" role="button" data-bs-id="'${data}'" data-bs-target="#mymodal" ><i class="fa-solid fa-trash"></a>` },
|
||||
cellClass: "datatable-icon",
|
||||
type: "number",
|
||||
hidden:true,
|
||||
},{
|
||||
select:1,
|
||||
type: 'date',
|
||||
format: 'dd.mm.yyyy',
|
||||
cellClass:"dt-datum",
|
||||
sortable: true,
|
||||
sort: "desc",
|
||||
},{
|
||||
select:2,
|
||||
type: 'string',
|
||||
cellClass:"dt-receiver",
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a onclick="collapseDetails(this,document.bookings)">${data}</a>` },
|
||||
|
||||
},{
|
||||
select:3,
|
||||
type: 'number',
|
||||
headerClass: "dt-amount",
|
||||
cellClass:"dt-amount",
|
||||
render: renderAmount
|
||||
}
|
||||
],
|
||||
template: (options, dom) => `<div class='${options.classes.top}'>
|
||||
<div class='float-start'>
|
||||
<a class="btn btn-sm btn-secondary" href="newBill">Neue Rechnung</a>
|
||||
<a class="btn btn-sm btn-secondary" href="newTransfer">Neuer Transfer</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class='${options.classes.container}'${options.scrollY.length ? ` style='height: ${options.scrollY}; overflow-Y: auto;'` : ""}></div>
|
||||
<div class='${options.classes.bottom}'>
|
||||
</div>`
|
||||
});
|
||||
loadOverviewData();
|
||||
}
|
||||
|
||||
function loadOverviewData(){
|
||||
document.bookings.setMessage("Loading Data");
|
||||
fetch("/getOverviewData", { method: "GET",headers: {"X-Requested-With": "XMLHttpRequest"},})
|
||||
.then(response => {
|
||||
let status = response.statusText;
|
||||
if (!response.ok) {
|
||||
throw "HTTP error: " + response.status + "; " + status;
|
||||
} else
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (document.bookings.hasRows){
|
||||
document.bookings.data.data.splice(0,document.bookings.data.data.length);
|
||||
document.bookings.hasRows = false;
|
||||
}
|
||||
//document.bookings.insert({data:data});
|
||||
document.bookings.insert({data:data.map(item => [item.id,item.datum,item.receiver,item.amount])});
|
||||
document.bookings.update(true);
|
||||
})
|
||||
.catch(err => {
|
||||
document.bookings.setMessage(err);
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
createDtOverviewBookings();
|
||||
});
|
||||
91
public/js/tab_scheduled.js
Normal file
91
public/js/tab_scheduled.js
Normal file
@@ -0,0 +1,91 @@
|
||||
var scheduleddata;
|
||||
var columnspez = columns;
|
||||
columnspez.splice(3, 0, { title: "Quelle",orderable:false, data: "source",className:"dt-source" });
|
||||
|
||||
function loadScheduledData(){
|
||||
document.scheduled.setMessage("Loading Data");
|
||||
fetch("/getScheduledData", { method: "GET",headers: {"X-Requested-With": "XMLHttpRequest"},})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (document.scheduled.hasRows){
|
||||
document.scheduled.data.data.splice(0,document.scheduled.data.data.length);
|
||||
document.scheduled.hasRows = false;
|
||||
}
|
||||
//document.scheduled.insert({data:data});
|
||||
document.scheduled.insert({data:data.map(item => [item.id,item.datum,item.receiver,item.source,item.amount])});
|
||||
document.scheduled.update(true);
|
||||
});
|
||||
}
|
||||
|
||||
function createDtScheduledBookings(){
|
||||
document.scheduled = new simpleDatatables.DataTable("#scheduled", {
|
||||
searchable: true,
|
||||
paging: false,
|
||||
classes: {
|
||||
active: "active",
|
||||
disabled: "disabled",
|
||||
table: "table table-striped table-sm",
|
||||
},
|
||||
data: {
|
||||
headings: ["","Datum","Empfänger","Quelle","Betrag"],
|
||||
data: scheduleddata,
|
||||
},
|
||||
rowRender: (row, tr, _index) => {
|
||||
//tr.childNodes[1].childNodes[0].attributes.href = `editBill/${row.cells[0].data}`;
|
||||
tr.childNodes[1].attributes.onclick = `location.href='editScheduled/${row.cells[0].data}'`;
|
||||
|
||||
// $(row).addClass('text-bg-warning');
|
||||
// tr.childNodes[2].attributes.onclick = `collapseDetails(this, ${_index})`;
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
select:0,
|
||||
render: (data, _cell, _dataIndex, _cellIndex) => { return `<a data-bs-toggle="modal" role="button" data-bs-id="${data}" data-bs-target="#mymodalDelete" ><i class="fa-solid fa-trash"></a>` },
|
||||
cellClass: "datatable-icon",
|
||||
type: "number",
|
||||
sort: "desc",
|
||||
},{
|
||||
select:1,
|
||||
type: 'date',
|
||||
format: 'dd.mm.yyyy',
|
||||
cellClass:"dt-datum",
|
||||
sortable: true,
|
||||
},{
|
||||
select:2,
|
||||
type: 'string',
|
||||
cellClass:"dt-receiver",
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a onclick="collapseDetails(this,document.bookings)">${data}</a>` },
|
||||
|
||||
},{
|
||||
select:3,
|
||||
type: 'string',
|
||||
cellClass:"dt-source",
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a onclick="collapseDetails(this,document.bookings)">${data}</a>` },
|
||||
|
||||
},{
|
||||
select:4,
|
||||
type: 'number',
|
||||
headerClass: "dt-amount",
|
||||
cellClass:"dt-amount",
|
||||
render: renderAmount
|
||||
}
|
||||
],
|
||||
template: (options, dom) => `<div class='${options.classes.top}'>
|
||||
<div class='float-start'>
|
||||
<a class="btn btn-sm btn-secondary" href="newScheduled">Neue Auto Rechnung</a>
|
||||
<a class="btn btn-sm btn-secondary" href="newScheduledTransfer">Neuer Auto Transfer</a>
|
||||
</div>
|
||||
<div class='${options.classes.search} float-end'>
|
||||
<input class='${options.classes.input}' placeholder='Search' type='search' title='${options.labels.searchTitle}'${dom.id ? ` aria-controls="${dom.id}"` : ""}>
|
||||
</div>
|
||||
</div>
|
||||
<div class='${options.classes.container}'${options.scrollY.length ? ` style='height: ${options.scrollY}; overflow-Y: auto;'` : ""}></div>
|
||||
<div class='${options.classes.bottom}'>
|
||||
</div>`
|
||||
});
|
||||
loadScheduledData();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
createDtScheduledBookings();
|
||||
})
|
||||
99
public/js/tab_todos.js
Normal file
99
public/js/tab_todos.js
Normal file
@@ -0,0 +1,99 @@
|
||||
var todosdata;
|
||||
|
||||
function loadToDosData(){
|
||||
document.todos.setMessage("Loading Data");
|
||||
fetch("/getToDosData", { method: "GET",headers: {"X-Requested-With": "XMLHttpRequest"},})
|
||||
.then(response => {
|
||||
let status = response.statusText;
|
||||
if (!response.ok) {
|
||||
throw "HTTP error: " + response.status + "; " + status;
|
||||
} else
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (document.todos.hasRows){
|
||||
document.todos.data.data.splice(0,document.todos.data.data.length);
|
||||
document.todos.hasRows = false;
|
||||
}
|
||||
document.todos.insert({data:data.map(item => [item.id, item.datum, item.receiver,item.amount])});
|
||||
document.todos.update(true);
|
||||
})
|
||||
.catch(err => {
|
||||
document.todos.setMessage(err);
|
||||
});
|
||||
}
|
||||
function createDtToDos(){
|
||||
document.todos = new simpleDatatables.DataTable("#todos", {
|
||||
searchable: true,
|
||||
paging: true,
|
||||
classes: {
|
||||
active: "active",
|
||||
disabled: "disabled",
|
||||
selector: "form-select",
|
||||
paginationList: "pagination",
|
||||
paginationListItem: "page-item",
|
||||
paginationListItemLink: "page-link",
|
||||
table: "table table-striped table-sm",
|
||||
},
|
||||
data: {
|
||||
headings: ["","Datum","Empfänger","Betrag"],
|
||||
data: todosdata,
|
||||
},
|
||||
rowRender: (row, tr, _index) => {
|
||||
tr.childNodes[1].attributes.onclick = `location.href='editBill/${row.cells[0].data}'`;
|
||||
},
|
||||
|
||||
columns: [
|
||||
{
|
||||
select:0,
|
||||
// render: (data, _cell, _dataIndex, _cellIndex) => { return `<a data-bs-toggle="modal" role="button" data-bs-id="'${data}'" data-bs-target="#mymodal" ><i class="fa-solid fa-trash"></a>` },
|
||||
cellClass: "datatable-icon",
|
||||
type: "number",
|
||||
hidden:true,
|
||||
},{
|
||||
select:1,
|
||||
type: 'date',
|
||||
format: 'dd.mm.yyyy',
|
||||
cellClass:"dt-datum",
|
||||
sortable: true,
|
||||
sort: "desc",
|
||||
},{
|
||||
select:2,
|
||||
type: 'string',
|
||||
cellClass:"dt-receiver",
|
||||
},{
|
||||
select:3,
|
||||
type: 'number',
|
||||
headerClass: "dt-amount",
|
||||
cellClass:"dt-amount",
|
||||
render: renderAmount
|
||||
}
|
||||
],
|
||||
template: (options, dom) => `<div class='${options.classes.top}'>
|
||||
<div class='float-start'>
|
||||
<a class="btn btn-sm btn-secondary" data-bs-toggle="modal" role="button" data-bs-target="#mySnycModal" onclick="syncScheduled(this)">Synch</a>
|
||||
</div>
|
||||
<div class='${options.classes.search} float-end'>
|
||||
<input class='${options.classes.input}' placeholder='Search' type='search' title='${options.labels.searchTitle}'${dom.id ? ` aria-controls="${dom.id}"` : ""}>
|
||||
</div>
|
||||
</div>
|
||||
<div class='${options.classes.container}'${options.scrollY.length ? ` style='height: ${options.scrollY}; overflow-Y: auto;'` : ""}></div>
|
||||
<div class='${options.classes.bottom}'>
|
||||
<div class='float-start'>
|
||||
<div class='datatable-dropdown'>
|
||||
<label>
|
||||
<select class='${options.classes.selector}'></select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class='float-end'>
|
||||
<nav class='${options.classes.pagination}'></nav>
|
||||
</div>
|
||||
</div>`
|
||||
});
|
||||
loadToDosData();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
createDtToDos();
|
||||
});
|
||||
@@ -1,3 +1,11 @@
|
||||
const renderAmount = function(data, _cell, _dataIndex, _cellIndex) {
|
||||
var ret = (Number(data)<0)?'<span style="color:red;">':'<span>';
|
||||
ret += new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(data);
|
||||
ret += '</span>';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
var colBetrag = {
|
||||
title: "Betrag",
|
||||
orderable:false,
|
||||
@@ -47,29 +55,6 @@ function alert(alertPlaceholder, message, type) {
|
||||
alertPlaceholder.append(wrapper);
|
||||
}
|
||||
|
||||
function deleteId(id, table) {
|
||||
if (table == "scheduled")
|
||||
cmnd = "deleteScheduled";
|
||||
else
|
||||
cmnd = "deleteBill";
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "/Ajax/"+cmnd,
|
||||
data: {"id" : id}, // serializes the form's elements.
|
||||
success: function(data){
|
||||
var ph = document.getElementById('alertbox');
|
||||
alert(ph,"erfolgreich gelöscht",'success');
|
||||
$('#'+table).DataTable().ajax.reload();
|
||||
},
|
||||
error: function(data){
|
||||
var ph = document.getElementById('alertbox');
|
||||
alert(ph,"Fehler beim löschen",'danger');
|
||||
$('#'+table).DataTable().ajax.reload();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function formatDetails ( d ) {
|
||||
details = '';
|
||||
str='';
|
||||
@@ -104,20 +89,22 @@ function formatDetails ( d ) {
|
||||
// null
|
||||
// ] )
|
||||
// } );
|
||||
function collapseDetails(element, table){
|
||||
var tr = element.closest('tr');
|
||||
var row = table.row( tr );
|
||||
function collapseDetails(e,index){
|
||||
console.log(e,index);
|
||||
|
||||
if ( row.child.isShown() ) {
|
||||
// This row is already open - close it
|
||||
row.child.hide();
|
||||
tr.removeClass('shown');
|
||||
}
|
||||
else {
|
||||
// Open this row
|
||||
row.child( formatDetails(row.data()) ).show();
|
||||
tr.addClass('shown');
|
||||
}
|
||||
var tr = e.closest('tr');
|
||||
// var row = table.row( tr );
|
||||
|
||||
// if ( row.child.isShown() ) {
|
||||
// // This row is already open - close it
|
||||
// row.child.hide();
|
||||
// tr.removeClass('shown');
|
||||
// }
|
||||
// else {
|
||||
// // Open this row
|
||||
// row.child( formatDetails(row.data()) ).show();
|
||||
// tr.addClass('shown');
|
||||
// }
|
||||
}
|
||||
|
||||
function getId(ele, table) {
|
||||
@@ -126,21 +113,28 @@ function getId(ele, table) {
|
||||
return row.data().id;
|
||||
}
|
||||
|
||||
$(document).ready(function(){
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
var myModal = document.getElementById('mymodal');
|
||||
const modal = new bootstrap.Modal(myModal);
|
||||
$("#modal_ok").click(function (e) {
|
||||
modal.hide();
|
||||
deleteId(myModal.getAttribute('data-bs-id'), myModal.getAttribute('data-bs-table'));
|
||||
var myModalDelete = document.getElementById('mymodalDelete');
|
||||
|
||||
myModalDelete.addEventListener('show.bs.modal', function (event) {
|
||||
var button = event.relatedTarget;
|
||||
var id = button.getAttribute('data-bs-id');
|
||||
let tab = button.closest('table').id; // table row ID
|
||||
myModalDelete.setAttribute('data-bs-id',id);
|
||||
myModalDelete.setAttribute('data-bs-table',tab);
|
||||
var modalTitle = myModalDelete.querySelector('.modal-title');
|
||||
modalTitle.textContent = 'Lösche Eintrag Nr. ' + id;
|
||||
});
|
||||
|
||||
myModal.addEventListener('show.bs.modal', function (event) {
|
||||
var button = event.relatedTarget;
|
||||
table = button.closest('table').id; // table row ID
|
||||
var id = button.getAttribute('data-bs-id');
|
||||
let table = button.getAttribute('data-bs-table');
|
||||
myModal.setAttribute('data-bs-id',id);
|
||||
myModal.setAttribute('data-bs-table',table);
|
||||
var modalTitle = myModal.querySelector('.modal-title');
|
||||
modalTitle.textContent = 'Lösche Eintrag Nr. ' + id;
|
||||
});
|
||||
|
||||
document.getElementById('modal_delete').addEventListener('click', deleteEntry );
|
||||
});
|
||||
@@ -1,54 +0,0 @@
|
||||
var datatable;
|
||||
var todos;
|
||||
|
||||
$(document).ready(function(){
|
||||
datatable = $('#bookings').DataTable({
|
||||
paging: false,
|
||||
searching:true,
|
||||
scrollX:false,
|
||||
info:false,
|
||||
order: [[ 1, 'desc' ]],
|
||||
ajax: { url: '/Ajax/getOverviewData', dataSrc:''},
|
||||
layout: {
|
||||
topStart: {
|
||||
buttons: [
|
||||
{text:'Neue Rechnung',className:'btn-sm',action: function ( e, dt, node, config ) {
|
||||
location.href = '/newBill/';
|
||||
}},
|
||||
]
|
||||
},
|
||||
topEnd: 'search'
|
||||
},
|
||||
// dom: '<"toolbar">frt',
|
||||
columns: columns,
|
||||
});
|
||||
// $("div.toolbar").html('<a class="btn-sm btn-secondary" href="/newBill" role="button">Neuer Eintrag</a>');
|
||||
// Add event listener for opening and closing details
|
||||
$('#bookings tbody').on('click', 'td.dt-receiver', function () {collapseDetails($(this), datatable);} );
|
||||
$('#bookings tbody').on('click', 'td.dt-datum', function () {location.href = '/editBill/'+getId($(this),datatable);});
|
||||
$('#bookings tbody').on('click', 'table.tabdet', function () {location.href = '/editBill/'+$(this).attr('data-bs-id');});
|
||||
|
||||
todos = $('#todos').DataTable({
|
||||
paging: true,
|
||||
searching:true,
|
||||
scrollX:false,
|
||||
info:true,
|
||||
order: [[ 1, 'desc' ]],
|
||||
ajax: { url: '/Ajax/getToDosData', dataSrc:''},
|
||||
layout: {
|
||||
topStart: {
|
||||
buttons: [
|
||||
{text:'Sync',className:'btn-sm',action: syncScheduled},
|
||||
]
|
||||
},
|
||||
topEnd: 'search'
|
||||
},
|
||||
// dom: '<"top"i<"syncbutton">>frt<"bottom"lp><"clear">',
|
||||
columns: columns,
|
||||
});
|
||||
// $("div.syncbutton").html('<a class="btn-sm btn-secondary" href="/syncScheduled" role="button">Sync</a>');
|
||||
// Add event listener for opening and closing details
|
||||
$('#todos tbody').on('click', 'td.dt-receiver', function () {collapseDetails($(this), todos);} );
|
||||
$('#todos tbody').on('click', 'td.dt-datum', function () {location.href = '/editBill/'+getId($(this),todos);});
|
||||
$('#todos tbody').on('click', 'table.tabdet', function () {location.href = '/editBill/'+$(this).attr('data-bs-id');});
|
||||
});
|
||||
Reference in New Issue
Block a user