61 Commits
Author SHA1 Message Date
OpenXE 62f6df1aeb fibu_buchungen added error when startdate is not set 2023-04-23 17:18:51 +02:00
OpenXE 828c1b1a75 Kontoauszuege removed "new" button. 2023-04-23 16:54:52 +02:00
OpenXE 7de88ca3b5 gutschrift freigabe with our without offsettung against rechnung, with offsetting creates fibu_buchung 2023-04-21 14:59:02 +02:00
OpenXE 5794301826 fibu_buchungen db_schema changed views, removed gutschrift vs. rechnung, fibu_objekte independent from zahlungsstatus 2023-04-21 14:52:48 +02:00
OpenXE 1a28b5d75b Prerelease 1.9, added EGPL 2023-04-18 19:14:59 +02:00
OpenXE df292c9c02 db_schema.json revert changes from 95d26d5c6e database upgrade to utf8mb4
reverted change from varchar(255) to text for many columns, due to utf8mb4 problems
2023-04-18 11:54:12 +02:00
OpenXE f0a24b7e5b ticket system improved logging on invalid date 2023-04-17 18:21:43 +02:00
OpenXE 50df55e35e bugfix auftrag offene status <> 'storniert' 2023-04-17 13:45:34 +02:00
OpenXE 4720cc8e94 fibu_buchungen einzelzuordnen multifilter 2023-04-15 18:45:09 +02:00
OpenXE 64d6b90312 fibu_buchungen usability improvements 2023-04-15 10:48:47 +02:00
OpenXE 17bdb1c5e1 auftrag set vorkasse_ok according to fibu_buchungen 2023-04-13 21:58:11 +02:00
OpenXE c4eaaa966a removed fints-hbci, white-cup-filled-by-coffee.jpg 2023-04-12 22:16:52 +02:00
OpenXE a43ac720b6 fibu_buchungen single with sachkonto 2023-04-11 19:52:58 +02:00
OpenXE 170a33687f fibu_buchungen views fixed empty date on kontorahmen 2023-04-11 16:41:20 +02:00
OpenXE ea6a6a5dda rechnung removed all updates of ist, except from fibu_buchungen 2023-04-11 15:40:23 +02:00
OpenXE 69172672b2 fibu_buchhaltung belege zuordnen multi option 2023-04-11 15:20:40 +02:00
OpenXE 667b70eaf5 fibu_buchungen booking to kontorahmen 2023-04-08 17:48:39 +02:00
OpenXE 44af8f3b3d Bugfix erpapi lagernummern typo 2023-04-07 18:17:57 +02:00
OpenXE 82fc367405 fibu_buchungen einzelzuordnung 2023-04-06 15:33:53 +02:00
OpenXE 828af9ab50 fibu_buchungen check saldo for vorschlag 2023-04-05 20:38:31 +02:00
OpenXE e79f2839e2 fibu_objekte_view added sachkonto and is_beleg filter 2023-04-05 12:52:50 +02:00
OpenXE 7aab51a390 fibu_buchungen vorschlag now includes saldo info 2023-04-05 12:32:10 +02:00
OpenXE 3dfba163df fibu_buchungen zuordnen with tablesearch instead of easytable 2023-04-05 11:07:12 +02:00
OpenXE 4a4b1f8320 bugfix import kontoauszuege importfehler 2023-04-05 11:02:06 +02:00
OpenXE 03f0f7217b rechnung & gutschrift set zahlungsstatus according to saldo 2023-04-05 11:01:16 +02:00
OpenXE c6a4cf0d23 Usability improvement kontoauszuege and buchungen 2023-04-04 14:15:01 +02:00
OpenXE 92f016d06b bugfix kontoauszuege import decimals and sum display 2023-04-04 13:48:40 +02:00
OpenXE 222b0ac239 importvorlage kontoauszuege 2.betrag 2023-04-04 11:59:53 +02:00
OpenXE 1e59009862 gutschrift mark as offen or bezahlt rework 2023-04-04 11:34:07 +02:00
OpenXE 76740aee02 db_schema changed reference in fibu_buchungen_view from fibu_objekte to fibu_objekte_view 2023-04-04 10:59:49 +02:00
OpenXE 06bc38e66a fibu_buchungen improved cache refresh 2023-04-03 21:17:59 +02:00
OpenXE ad4599e381 fibu_buchungen_alle converted to cached view for better performance 2023-04-03 20:25:00 +02:00
OpenXE b1349afb6b fibu_buchungen bugfix search with multiple results 2023-04-03 16:47:44 +02:00
OpenXE 820dc9fec6 kontoauszuege bugfix importer date and filter import errors 2023-04-03 16:23:00 +02:00
OpenXE 46f9e0728d fibu_buchungen add date limit (firmendaten) 2023-04-03 16:10:28 +02:00
OpenXE 8bdedcb72f Develop version 1.8.1 2023-04-02 17:44:11 +02:00
OpenXE ebd50b4f28 fibu_buchungen document auto assign 2023-04-02 12:23:51 +02:00
OpenXE 85094921a0 bugfix inverted UNIQUE parameter in db_schema and mustal 2023-04-02 11:46:17 +02:00
OpenXE d97f41e293 db_schema adjustments mainly utf8mb3 2023-04-02 10:23:07 +02:00
OpenXE b701a880a4 Merge remote-tracking branch 'github/master' into develop.1.8.1 2023-04-01 22:39:15 +02:00
OpenXE 2b573268fa fibu buchungen 2023-04-01 20:42:37 +02:00
OpenXE 689fdb0490 Kontoauszuege konto overview and saldo 2023-03-30 19:29:46 +02:00
OpenXE c223e7c956 mustal improvement view handling 2023-03-30 15:21:33 +02:00
OpenXE a15d7b0b41 database utf8 rework 2023-03-30 15:21:09 +02:00
OpenXE 3715c2f205 firmendaten hotfix freifelder 2023-03-30 12:33:38 +02:00
OpenXE 95d26d5c6e database upgrade to utf8mb4 2023-03-30 11:24:14 +02:00
OpenXE 5bc7a64c8c mustal improvement on collation handling 2023-03-30 11:19:46 +02:00
OpenXE b7153c423c fibu_buchungen added, rework of zahlungen auftrag, rechnung, gutschrift 2023-03-28 12:30:57 +02:00
OpenXE 1637bf965a bugfix mustal default values forced lower case 2023-03-28 12:18:41 +02:00
OpenXE 9a6ed1ae75 fibu_buchungen_alle with type and id of editable item 2023-03-27 16:31:30 +02:00
OpenXE 49dfd255e4 Bugfix briefpapier freitexte width 2023-03-26 13:26:49 +02:00
OpenXE 791a12b731 Bugfix user avatar 2023-03-26 13:23:15 +02:00
OpenXE 62e16cfcc1 fibu_buchungen database definitions 2023-03-25 21:23:20 +01:00
OpenXE c220639e82 Zahlungsstatus Rechnung Gutschrift reworked with fibu_buchungen 2023-03-25 17:50:04 +01:00
OpenXE 6a566a99af Kontoauszuege module & importer 2023-03-22 20:37:17 +01:00
OpenXE e356051f5a Zahlungen improvements 2023-03-22 14:33:34 +01:00
OpenXE 1f52278758 mustal added handling of UNIQUE keys 2023-03-21 20:20:44 +01:00
OpenXE ab91715c20 Zahlungen minidetail and collation of relevant documents as tree 2023-03-16 11:49:45 +01:00
OpenXE 8dd78dfa55 Bugfix lager wert calculation of prices added geloescht != 1 and date range 2023-03-14 13:40:14 +01:00
OpenXE 71883d34ae Zahlungseingang Minidetail hacked rechnung, gutschrift 2023-03-13 17:12:38 +01:00
OpenXE 73dbbb061a Geschaeftskonto module restored (basic variant) 2023-03-13 14:22:39 +01:00
145 changed files with 15750 additions and 18177 deletions
@@ -309,6 +309,7 @@ final class MailMessageData implements MailMessageInterface, JsonSerializable
}
$dateTime = date_create($date->getValue());
if ($dateTime === false) {
throw new InvalidArgumentException('Invalid date: '.$date->getValue());
return null;
}
@@ -511,7 +511,10 @@ class TicketImportHelper
continue;
}
} catch (Throwable $e) {
$this->logger->error('Error during email import '.$messageNumber, ['message' => substr(print_r($message,true),0,1000)]);
$exception_message = $e->getMessage();
$this->logger->error('Error during email import '.$messageNumber, ['exc-message' => $exception_message ,'message2' => substr(print_r($message,true),0,1000)]);
continue;
}
}
@@ -573,14 +576,17 @@ class TicketImportHelper
$this->logger->debug('Text (converted)',['plain' => $action, 'html' => $action_html]);
// Import database emailbackup
$date = $message->getDate();
if (is_null($date)) { // This should not be happening -> Todo check getDate function
$this->logger->debug('Null date',['subject' => $message->getSubject(), $message->getHeader('date')->getValue()]);
return(false);
} else {
$timestamp = $date->getTimestamp();
$frommd5 = md5($from . $subject . $timestamp);
try {
$date = $message->getDate();
}
catch (exception $e) {
$this->logger->debug('Invalid date',['exc-message' => $e->getMessage(),'subject' => $message->getSubject(), $message->getHeader('date')->getValue()]);
return(false);
}
$timestamp = $date->getTimestamp();
$frommd5 = md5($from . $subject . $timestamp);
$empfang = $date->format('Y-m-d H:i:s');
$sql = "SELECT COUNT(id)
FROM `emailbackup_mails`
+40 -18
View File
@@ -6081,11 +6081,11 @@ r.land as land, p.abkuerzung as projekt, r.zahlungsweise as zahlungsweise,
$heading = array('', '', 'Gutschrift', 'Vom', 'Kd-Nr.', 'Kunde', 'Land', 'Projekt',
'Zahlweise', 'Betrag (brutto)', 'bezahlt','RE-Nr.', 'Status','Monitor' ,'Men&uuml;'
'Zahlweise', 'Betrag (brutto)', 'Zahlstatus','Differenz','RE-Nr.', 'Status','Monitor' ,'Men&uuml;'
);
$width = array('1%', '1%', '10%', '10%', '10%', '25%', '5%', '1%', '1%', '1%', '1%', '1%','5%', '1%','1%', '1%');
$findcols = array('open', 'r.belegnr', 'r.belegnr', 'r.datum', 'adr.kundennummer', 'r.name', 'r.land', 'p.abkuerzung', 'r.zahlungsweise', 'r.soll','re.belegnr', 'r.zahlungsstatus', 'r.status', 'pt.payement_status' ,'id');
$width = array('1%', '1%', '10%', '10%', '10%', '25%', '5%', '1%', '1%', '1%', '1%', '1%', '1%','5%', '1%','1%', '1%');
$findcols = array('open', 'r.belegnr', 'r.belegnr', 'r.datum', 'adr.kundennummer', 'r.name', 'r.land', 'p.abkuerzung', 'r.zahlungsweise', 'r.soll', 'r.zahlungsstatus','r.soll-r.ist', 're.belegnr', 'r.status', 'id');
$searchsql = array('DATE_FORMAT(r.datum,\'%d.%m.%Y\')', 'r.belegnr', 'adr.kundennummer', 'r.name', 'r.land', 'p.abkuerzung','re.belegnr', 'r.status', "FORMAT(r.soll,2{$extended_mysql55})", 'adr.freifeld1', 'r.ihrebestellnummer','r.internebezeichnung','au.internet');
$defaultorder = 13; //Optional wenn andere Reihenfolge gewuenscht
@@ -6127,20 +6127,31 @@ r.land as land, p.abkuerzung as projekt, r.zahlungsweise as zahlungsweise,
$menu .= "</table>";
$menucol = 14;
$menucol = 15;
$parameter = $this->app->User->GetParameter('table_filter_gutschrift');
$parameter = base64_decode($parameter);
$parameter = json_decode($parameter, true);
// SQL statement
$sql = "SELECT SQL_CALC_FOUND_ROWS r.id,'<img src=./themes/{$this->app->Conf->WFconf['defaulttheme']}/images/details_open.png class=details>' as open, concat('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',r.id,'\" />')as auswahl,
r.belegnr,
DATE_FORMAT(r.datum,'%d.%m.%Y') as vom, adr.kundennummer as kundennummer,
CONCAT(" . $this->app->erp->MarkerUseredit("r.name", "r.useredittimestamp") . ", if(r.internebezeichnung!='',CONCAT('<br><i style=color:#999>',r.internebezeichnung,'</i>'),'')) as kunde,
r.land as land, p.abkuerzung as projekt, r.zahlungsweise as zahlungsweise,
FORMAT(r.soll,2{$extended_mysql55}) as soll, r.zahlungsstatus as zahlung, re.belegnr as rechnung, UPPER(r.status) as status,
".$this->IconsSQLReturnOrder()." ,r.id
$sql = "SELECT SQL_CALC_FOUND_ROWS
r.id,
'<img src=./themes/{$this->app->Conf->WFconf['defaulttheme']}/images/details_open.png class=details>' as open,
concat('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',r.id,'\" />')as auswahl,
r.belegnr,
DATE_FORMAT(r.datum,'%d.%m.%Y') as vom,
adr.kundennummer as kundennummer,
CONCAT(" . $this->app->erp->MarkerUseredit("r.name", "r.useredittimestamp") . ", if(r.internebezeichnung!='',CONCAT('<br><i style=color:#999>',r.internebezeichnung,'</i>'),'')) as kunde,
r.land as land,
p.abkuerzung as projekt,
r.zahlungsweise as zahlungsweise,
".$this->app->erp->FormatMenge('r.soll',2)." as soll,
r.zahlungsstatus as zahlung,
".$this->app->erp->FormatMenge('r.soll-r.ist',2)." as differenz,
re.belegnr as rechnung,
UPPER(r.status) as status,
".$this->IconsSQLReturnOrder().",
r.id
FROM gutschrift r
LEFT JOIN rechnung re ON re.id=r.rechnungid
LEFT JOIN projekt p ON p.id=r.projekt
@@ -6551,13 +6562,24 @@ r.land as land, p.abkuerzung as projekt, r.zahlungsweise as zahlungsweise,
// $columnfilter = true;
// SQL statement
$sql = "SELECT SQL_CALC_FOUND_ROWS r.id,'<img src=./themes/{$this->app->Conf->WFconf['defaulttheme']}/images/details_open.png class=details>' as open,concat('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',r.id,'\" />')as auswahl, r.belegnr, DATE_FORMAT(r.datum,'%d.%m.%Y') as vom,
if(r.kundennummer <> '',r.kundennummer,adr.kundennummer),
CONCAT(" . $this->app->erp->MarkerUseredit("r.name", "r.useredittimestamp") . ", if(r.internebezeichnung!='',CONCAT('<br><i style=color:#999>',r.internebezeichnung,'</i>'),'')) as kunde,
r.land as land, p.abkuerzung as projekt, r.zahlungsweise as zahlungsweise, FORMAT(r.soll,2{$extended_mysql55} ) as soll, ifnull(r.waehrung,'EUR'),
if(r.soll-r.ist+r.skonto_gegeben!=0 AND r.ist > 0 AND r.zahlungsstatus!='bezahlt','teilbezahlt',r.zahlungsstatus) as zahlung,
if(r.soll-r.ist+r.skonto_gegeben!=0 AND r.ist > 0,FORMAT(r.ist-r.soll+r.skonto_gegeben,2{$extended_mysql55}),FORMAT((r.soll-r.ist+r.skonto_gegeben)*-1,2{$extended_mysql55})) as fehlt, if(r.status = 'storniert' AND r.teilstorno = 1,'TEILSTORNO',UPPER(r.status)) as status, ".(!empty($zusatzcols)?implode(', ',$zusatzcols).',':'')." r.id
$sql = "SELECT SQL_CALC_FOUND_ROWS
r.id,
'<img src=./themes/{$this->app->Conf->WFconf['defaulttheme']}/images/details_open.png class=details>' as open,
concat('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',r.id,'\" />') as auswahl,
r.belegnr,
DATE_FORMAT(r.datum,'%d.%m.%Y') as vom,
if(r.kundennummer <> '',r.kundennummer,adr.kundennummer),
CONCAT(" . $this->app->erp->MarkerUseredit("r.name", "r.useredittimestamp") . ", if(r.internebezeichnung!='',CONCAT('<br><i style=color:#999>',r.internebezeichnung,'</i>'),'')) as kunde,
r.land as land,
p.abkuerzung as projekt,
r.zahlungsweise as zahlungsweise,
FORMAT(r.soll,2{$extended_mysql55} ) as soll,
ifnull(r.waehrung,'EUR'),
if(r.soll-r.ist=0 AND r.ist > 0 AND r.zahlungsstatus!='bezahlt','teilbezahlt',r.zahlungsstatus) as zahlung,
if(r.soll-r.ist!=0 AND r.ist > 0,FORMAT(r.ist-r.soll,2{$extended_mysql55}),FORMAT((r.soll-r.ist)*-1,2{$extended_mysql55})) as fehlt,
if(r.status = 'storniert' AND r.teilstorno = 1,'TEILSTORNO',UPPER(r.status)) as status,
".(!empty($zusatzcols)?implode(', ',$zusatzcols).',':'')."
r.id
FROM rechnung r LEFT JOIN projekt p ON p.id=r.projekt LEFT JOIN adresse adr ON r.adresse=adr.id LEFT JOIN auftrag au ON au.id = r.auftragid ";
if(isset($parameter['artikel']) && !empty($parameter['artikel'])) {
$artikelid = $this->app->DB->Select("SELECT id FROM artikel where geloescht != 1 AND nummer != 'DEL' AND nummer != '' AND nummer = '".$this->app->DB->real_escape_string(reset(explode(' ',trim($parameter['artikel']))))."' LIMIT 1");
+10741 -7814
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -415,6 +415,10 @@ function upgrade_main(string $directory,bool $verbose, bool $check_git, bool $do
$counter++;
echo_out("\rUpgrade step $counter of $number_of_statements... ");
if ($verbose) {
echo_out("\n".$sql."\n");
}
$query_result = mysqli_query($mysqli, $sql);
if (!$query_result) {
$error = " not ok: ". mysqli_error($mysqli);
+60 -25
View File
@@ -79,20 +79,22 @@ function mustal_load_tables_from_db(string $host, string $schema, string $user,
}
// Get db_def and views
$sql = "SHOW FULL tables WHERE Table_type = 'BASE TABLE'";
$sql = "SHOW TABLE STATUS WHERE engine IS NOT NULL";
$query_result = mysqli_query($mysqli, $sql);
if (!$query_result) {
return(array());
}
while ($row = mysqli_fetch_assoc($query_result)) {
$table = array();
$table['name'] = $row['Tables_in_'.$schema];
$table['type'] = $row['Table_type'];
$table['name'] = $row['Name'];
$table['collation'] = $row['Collation'];
$table['type'] = 'BASE TABLE';
$tables[] = $table; // Add table to list of tables
}
// Get and add columns of the table
foreach ($tables as &$table) {
$sql = "SHOW FULL COLUMNS FROM ".$table['name'];
$query_result = mysqli_query($mysqli, $sql);
@@ -109,6 +111,10 @@ function mustal_load_tables_from_db(string $host, string $schema, string $user,
$column['Default'] = mustal_mysql_put_text_type_in_quotes($column['Type'],$column['Default']);
}
if (empty($column['Collation']) && mustal_is_string_type($column['Type'])) {
$column['Collation'] = $table['collation'];
}
$columns[] = $column; // Add column to list of columns
}
$table['columns'] = $columns;
@@ -135,6 +141,13 @@ function mustal_load_tables_from_db(string $host, string $schema, string $user,
$composed_key['Key_name'] = $key['Key_name'];
$composed_key['Index_type'] = $key['Index_type'];
$composed_key['columns'][] = $key['Column_name'];
if ($key['Key_name'] != 'PRIMARY') {
$composed_key['Non_unique'] = ($key['Non_unique'] == 1)?'':'UNIQUE';
} else {
$composed_key['Non_unique'] = '';
}
$composed_keys[] = $composed_key;
} else {
// Given key, add column
@@ -161,9 +174,16 @@ function mustal_load_tables_from_db(string $host, string $schema, string $user,
foreach ($views as &$view) {
$sql = "SHOW CREATE VIEW ".$view['name'];
$query_result = mysqli_query($mysqli, $sql);
try {
$query_result = mysqli_query($mysqli, $sql);
}
catch (exception $e) {
$query_result = false; // VIEW is erroneous
}
if (!$query_result) {
return(array());
$view['Create'] = '';
continue;
}
$viewdef = mysqli_fetch_assoc($query_result);
@@ -330,19 +350,19 @@ function mustal_compare_table_array(array $nominal, string $nominal_name, array
// Compare the properties of the sql_indexs
if ($check_column_definitions) {
$found_sql_index = $found_table['keys'][$sql_index_key];
foreach ($sql_index as $key => $value) {
if ($found_sql_index[$key] != $value) {
// if ($key != 'permissions') {
$compare_difference = array();
$compare_difference['type'] = "Key definition";
$compare_difference['table'] = $database_table['name'];
$compare_difference['key'] = $sql_index['Key_name'];
$compare_difference['property'] = $key;
$compare_difference[$nominal_name] = implode(',',$value);
$compare_difference[$actual_name] = implode(',',$found_sql_index[$key]);
$compare_differences[] = $compare_difference;
// }
$compare_difference = array();
$compare_difference['type'] = "Key definition";
$compare_difference['table'] = $database_table['name'];
$compare_difference['key'] = $sql_index['Key_name'];
$compare_difference['property'] = $key;
/* $compare_difference[$nominal_name] = implode(',',$value);
$compare_difference[$actual_name] = implode(',',$found_sql_index[$key]);*/
$compare_difference[$nominal_name] = $value;
$compare_difference[$actual_name] = $found_sql_index[$key];
$compare_differences[] = $compare_difference;
}
}
unset($value);
@@ -401,9 +421,11 @@ function mustal_compare_table_array(array $nominal, string $nominal_name, array
// Generate SQL to create or modify column
function mustal_column_sql_definition(string $table_name, array $column, array $reserved_words_without_quote) : string {
$column_is_string_type = mustal_is_string_type($column['Type']);
foreach($column as $key => &$value) {
$value = (string) $value;
$value = mustal_column_sql_create_property_definition($key,$value,$reserved_words_without_quote);
$value = mustal_column_sql_create_property_definition($key,$value,$reserved_words_without_quote,$column_is_string_type);
}
// Default handling here
@@ -422,7 +444,7 @@ function mustal_column_sql_definition(string $table_name, array $column, array $
}
// Generate SQL to modify a single column property
function mustal_column_sql_create_property_definition(string $property, string $property_value, array $reserved_words_without_quote) : string {
function mustal_column_sql_create_property_definition(string $property, string $property_value, array $reserved_words_without_quote, $column_is_string_type) : string {
switch ($property) {
case 'Type':
@@ -453,8 +475,10 @@ function mustal_column_sql_create_property_definition(string $property, string $
}
break;
case 'Collation':
if ($property_value != '') {
if ($property_value != '' && $column_is_string_type) {
$property_value = " COLLATE ".$property_value;
} else {
$property_value = "";
}
break;
default:
@@ -468,9 +492,9 @@ function mustal_column_sql_create_property_definition(string $property, string $
// Replaces different variants of the same function mustal_to allow comparison
function mustal_sql_replace_reserved_functions(array &$column, array $replacers) {
$result = strtolower($column['Default']);
$result = $column['Default'];
foreach ($replacers as $replace) {
if ($result == $replace[0]) {
if (strtolower($column['Default']) == $replace[0]) {
$result = $replace[1];
}
}
@@ -568,7 +592,7 @@ function mustal_calculate_db_upgrade(array $compare_def, array $db_def, array &$
$index_type = "";
}
$keystring = $index_type." KEY `".$key['Key_name']."` ";
$keystring = $index_type." ".$key['Non_unique']." KEY `".$key['Key_name']."` ";
}
$sql .= $comma.$keystring."(`".implode("`,`",$key['columns'])."`) ";
}
@@ -652,7 +676,7 @@ function mustal_calculate_db_upgrade(array $compare_def, array $db_def, array &$
if ($key_key !== false) {
$key = $table['keys'][$key_key];
$sql = "ALTER TABLE `$table_name` ADD KEY `".$key_name."` ";
$sql = "ALTER TABLE `$table_name` ADD ".$key['Non_unique']." KEY `".$key_name."` ";
$sql .= "(`".implode("`,`",$key['columns'])."`)";
$sql .= ";";
$upgrade_sql[] = $sql;
@@ -682,7 +706,7 @@ function mustal_calculate_db_upgrade(array $compare_def, array $db_def, array &$
$sql = "ALTER TABLE `$table_name` DROP KEY `".$key_name."`;";
$upgrade_sql[] = $sql;
$sql = "ALTER TABLE `$table_name` ADD KEY `".$key_name."` ";
$sql = "ALTER TABLE `$table_name` ADD ".$key['Non_unique']." KEY `".$key_name."` ";
$sql .= "(`".implode("`,`",$key['columns'])."`)";
$sql .= ";";
$upgrade_sql[] = $sql;
@@ -743,6 +767,17 @@ function mustal_calculate_db_upgrade(array $compare_def, array $db_def, array &$
array_unshift($upgrade_sql,"SET SQL_MODE='ALLOW_INVALID_DATES';","SET SESSION innodb_strict_mode=OFF;");
}
return($result);
}
// Check if given type is a string, relevant for collation
function mustal_is_string_type(string $type) {
$mustal_string_types = array('varchar','char','text','tinytext','mediumtext','longtext');
foreach($mustal_string_types as $string_type) {
if (stripos($type,$string_type) === 0) {
return(true);
}
}
return(false);
}
+1 -1
View File
@@ -1,7 +1,7 @@
<?php
$version="OSS";
$version_revision="1.8";
$version_revision="P.1.9";
$githash = file_get_contents("../githash.txt");
if (!empty($githash)) {
$version_revision .= " (".substr($githash,0,8).")";
+245 -6
View File
@@ -1517,6 +1517,11 @@ public function NavigationHooks(&$menu)
// return "replace(trim($spalte)+0,'.',',')";
}
function FormatUCfirst($spalte)
{
return ('CONCAT(UCASE(LEFT('.$spalte.', 1)),SUBSTRING('.$spalte.', 2))');
}
static function add_alias(string $text, $alias = false) {
if (empty($alias)) {
return($text);
@@ -2642,6 +2647,24 @@ public function NavigationHooks(&$menu)
return "if(" . $fieldstroke . ",CONCAT('<s>'," . $field . ",'</s>')," . $field . ")";
}
// @refactor DbHelper Komponente
// creates a CONCAT sql statement with strings or sql expressions
// Use like this: ConcatSQL('<a href=index.php?id=',['sql'] => 'id','>','click here</a>');
function ConcatSQL(array $fields) {
$result = "CONCAT(";
$comma = "";
foreach ($fields as $field) {
if (gettype($field) == 'array') {
$result .= $comma.$field['sql'];
} else {
$result .= $comma."'".$field."'";
}
$comma = ",";
}
$result .= ")";
return($result);
}
// @refactor Formater Komponente
function Dateinamen($text) {
$text = $this->UmlauteEntfernen($text);
@@ -7095,6 +7118,8 @@ title: 'Abschicken',
$navarray['menu']['admin'][$menu]['sec'][] = array('Arbeitsnachweis','arbeitsnachweis','list');
$navarray['menu']['admin'][$menu]['sec'][] = array('Gutschrift / '.$this->Firmendaten("bezeichnungstornorechnung"),'gutschrift','list');
$navarray['menu']['admin'][$menu]['sec'][] = array('Proformarechnung','proformarechnung','list');
$navarray['menu']['admin'][$menu]['sec'][] = array('Kontoausz&uuml;ge','kontoauszuege','list');
$navarray['menu']['admin'][$menu]['sec'][] = array('Buchungen','fibu_buchungen','list');
$navarray['menu']['admin'][$menu]['sec'][] = array('Abolauf','rechnungslauf','list');
$navarray['menu']['admin'][$menu]['sec'][] = array('Mahnwesen','mahnwesen','list');
@@ -12673,6 +12698,10 @@ function SendPaypalFromAuftrag($auftrag, $test = false)
//TODO zahlungsweisemodul
$zahlungsweise = strtolower($zahlungsweise);
/*
OLD CODE REPLACED BY FUNCTION IN auftrag.php / fibu_buchungen
if($zahlungsweisenmodule = $this->app->DB->SelectArr("SELECT id, modul, verhalten FROM zahlungsweisen WHERE type = '".$this->app->DB->real_escape_string($zahlungsweise)."' AND
(projekt = '$projekt' OR projekt = 0) ORDER BY projekt = '$projekt' DESC LIMIT 1
"))
@@ -12700,6 +12729,9 @@ function SendPaypalFromAuftrag($auftrag, $test = false)
$this->app->DB->Update("UPDATE auftrag SET vorkasse_ok='0' WHERE id='$auftrag' LIMIT 1");
}
}
*/
//nachnahme gebuehr check!!!!
//$nachnahme = $this->app->DB->Select("SELECT id FROM auftrag_position WHERE auftrag='$auftrag' AND nummer='200001' LIMIT 1");
$nachnahme = $this->app->DB->Select("SELECT COUNT(ap.id) FROM auftrag_position ap, artikel a WHERE ap.auftrag='$auftrag' AND ap.artikel=a.id AND a.porto=1 AND ap.preis >= 0
@@ -22193,8 +22225,8 @@ function ChargenMHDAuslagern($artikel, $menge, $lagerplatztyp, $lpid,$typ,$wert,
$this->app->DB->Delete("DELETE lager_charge FROM lager_charge INNER JOIN lager_platz ON lager_platz.id=lager_charge.lager_platz
WHERE lager_platz.verbrauchslager='1' AND lager_platz.id = '$regal'");
$this->app->DB->Delete("DELETE lager_seriennummer FROM lager_seriennummer
INNER JOIN lager_platz ON lager_platz.id=lager_seriennummer.lager_platz
$this->app->DB->Delete("DELETE FROM lager_seriennummern
INNER JOIN lager_platz ON lager_platz.id=lager_seriennummern.lager_platz
WHERE lager_platz.verbrauchslager='1' AND lager_platz.id = '$regal'");
$this->app->DB->Delete("DELETE lager_mindesthaltbarkeitsdatum FROM lager_mindesthaltbarkeitsdatum
@@ -22212,8 +22244,8 @@ function ChargenMHDAuslagern($artikel, $menge, $lagerplatztyp, $lpid,$typ,$wert,
$this->app->DB->Delete("DELETE lager_charge FROM lager_charge INNER JOIN lager_platz ON lager_platz.id=lager_charge.lager_platz
WHERE lager_platz.verbrauchslager='1'");
$this->app->DB->Delete("DELETE lager_seriennummer FROM lager_seriennummer
INNER JOIN lager_platz ON lager_platz.id=lager_seriennummer.lager_platz
$this->app->DB->Delete("DELETE FROM lager_seriennummern
INNER JOIN lager_platz ON lager_platz.id=lager_seriennummern.lager_platz
WHERE lager_platz.verbrauchslager='1'");
$this->app->DB->Delete("DELETE lager_mindesthaltbarkeitsdatum FROM lager_mindesthaltbarkeitsdatum
@@ -34500,7 +34532,7 @@ function Firmendaten($field,$projekt="")
$this->CopyBelegZwischenpositionen('rechnung',$id,'gutschrift',$newid);
$this->app->DB->Update("UPDATE gutschrift SET stornorechnung='$stornorechnung', ohne_briefpapier='".$ohnebriefpapier."' WHERE id='$newid,' LIMIT 1");
$this->app->DB->Update("UPDATE rechnung SET schreibschutz='1',status='storniert',zahlungsstatus='bezahlt' WHERE id='$id' LIMIT 1");
$this->app->DB->Update("UPDATE rechnung SET schreibschutz='1',status='storniert' WHERE id='$id' LIMIT 1");
$this->RechnungProtokoll($id, $grund);
$this->SchnellFreigabe("gutschrift",$newid);
return $newid;
@@ -35641,7 +35673,7 @@ function Firmendaten($field,$projekt="")
$rechnungid = $this->app->DB->Select("SELECT rechnungid FROM gutschrift WHERE id='$id' LIMIT 1");
if($rechnungid > 0 && $this->Firmendaten("mahnwesenmitkontoabgleich")=="1")
{
$this->app->DB->Update("UPDATE rechnung SET ist=0, zahlungsstatus='offen' WHERE id='$rechnungid' AND mahnwesenfestsetzen!=1 LIMIT 1");
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='offen' WHERE id='$rechnungid' AND mahnwesenfestsetzen!=1 LIMIT 1");
$this->RechnungNeuberechnen($rechnungid);
}
}
@@ -35819,6 +35851,213 @@ function Firmendaten($field,$projekt="")
}
}
/*
* Retrieve the associated documents regarding payments
* Gutschrift -> Rechnung -> Auftrag OR Verbindlichkeit
* Results array of ids, types, belegnr
*/
public function GetZahlungenAssociatedDocuments(int $id, string $type, string $lastlevel = 'auftrag') : array {
$assocs = array(
array(
'type' => 'auftrag',
'below' => 'rechnung',
),
array(
'above' => 'auftrag',
'type' => 'rechnung',
'below' => 'gutschrift'
),
array(
'above' => 'rechnung',
'type' => 'gutschrift'
),
array(
'type' => 'verbindlichkeit'
)
);
if ($id <= 0) {
throw new exception('no id provided');
}
if (!in_array($type, array('rechnung','gutschrift','auftrag','verbindlichkeit'))) {
throw new exception('invalid type '.$type);
}
$id = $this->app->Secure->GetGET('id');
// Go to highest level
$above = $assocs[array_search($type,array_column($assocs,'type'))]['above'];
while ($above) {
if ($type == $lastlevel) {
break;
}
$sql = "SELECT ".$above."id as id FROM ".$type." WHERE id = ".$id;
$above_id = $this->app->DB->SelectArr($sql)[0];
if (!empty($above)) {
$type = $above;
$id = $above_id['id'];
}
$above = $assocs[array_search($type,array_column($assocs,'type'))]['above'];
}
// Cascade down and retrieve all documents
$result_documents = array();
$ids = array($id);
$ref = 'id';
do {
$sql = "SELECT id, '".$type."' AS type, belegnr FROM ".$type." WHERE ".$ref." IN (".implode(",",$ids).")";
$result = $this->app->DB->SelectArr($sql);
if (!empty($result)) {
$result_documents = array_merge($result_documents, $result);
$ids = array_column($result,'id');
$ref = $type."id";
$type = $assocs[array_search($type,array_column($assocs,'type'))]['below'];
} else {
break;
}
} while ($type);
return($result_documents);
}
/*
* Calculate the payments of a document (rechnung, gutschrift, auftrag, verbindlichkeit)
* Results array of payments (datum, doc_type, doc_id, doc_inof, betrag, waehrung)
* Gutschrift -> Rechnungid, Rechnung -> Auftragid
*/
public function GetZahlungen(int $id, string $type, string $cascadelevel = '') : array {
if ($cascadelevel != '') {
$documents = $this->GetZahlungenAssociatedDocuments($id, $type, $cascadelevel);
} else {
$documents = array(array('id' => $id, 'type' => $type));
}
if (empty($documents)) {
return(array());
}
$ids = array();
foreach ($documents as $document) {
$ids[] = $document['type'].$document['id'];
}
$sql = "
SELECT
typ,
id,
".$this->app->erp->FormatDate('datum')." as datum,
doc_typ,
doc_id,
doc_info,
".$this->app->erp->FormatMenge('betrag',2)." as betrag,
waehrung
FROM
fibu_buchungen_alle
WHERE
CONCAT(typ,id) IN ('".implode("','",$ids)."')
ORDER BY
(SELECT datum) ASC
";
$result = $this->app->DB->SelectArr($sql);
if (empty($result)) {
return(array());
}
return($result);
}
/*
* Calculate the payment saldo information of a document
* Auftrag: gesamtsumme, rechnung: soll, gutschrift: soll verbindlichkeit: betrag
* returns array(array(betrag, waehrung)) one line per waehrung
*/
public function GetSaldenDokument(int $id, string $type, string $cascadelevel = '') : array {
if ($cascadelevel != '') {
$documents = $this->GetZahlungenAssociatedDocuments($id, $type, $cascadelevel);
} else {
$documents = array(array('id' => $id, 'type' => $type));
}
if (empty($documents)) {
return(array());
}
$ids = array();
foreach ($documents as $document) {
$ids[] = $document['type'].$document['id'];
}
$sql = "
SELECT
".$this->app->erp->FormatMenge('SUM(betrag)',2)." as betrag,
waehrung
FROM
fibu_buchungen_alle
WHERE
CONCAT(typ,id) IN ('".implode("','",$ids)."')
GROUP BY
waehrung";
$result = $this->app->DB->SelectArr($sql);
if (!empty($result)) {
return($result);
}
return(array());
}
/*
* Calculate the payment amount of a document
* Auftrag: gesamtsumme, rechnung: soll, gutschrift: soll verbindlichkeit: betrag
* returns array(betrag, waehrung) or empty array if multiple
*/
public function GetSaldoDokument(int $id, string $type) : array {
$sql = "
SELECT
SUM(betrag) as betrag,
waehrung
FROM
fibu_buchungen_alle
WHERE
typ = '".$type."' AND id = ".$id."
GROUP BY
waehrung";
$result = $this->app->DB->SelectArr($sql);
if (!empty($result)) {
if (count($result) == 1) {
return($result[0]);
}
}
return(array());
}
/*
* Create a fibu buchung
* using module fibu_buchungen
*/
public function fibu_buchungen_buchen(string $von_typ, int $von_id, string $nach_typ, int $nach_id, $betrag, string $waehrung, $datum, string $internebemerkung) {
$fibu_buchungen = $this->app->loadModule('fibu_buchungen', false);
if($fibu_buchungen !== null && method_exists($fibu_buchungen, 'fibu_buchungen_buchen')) {
return $fibu_buchungen->fibu_buchungen_buchen($von_typ, $von_id, $nach_typ, $nach_id, $betrag, $waehrung, $datum, $internebemerkung);
}
}
public function ANABREGSNeuberechnen($id,$art,$force=false)
{
if($id <= 0 || empty($art))
+14
View File
@@ -2072,6 +2072,20 @@ select a.kundennummer, (SELECT name FROM adresse a2 WHERE a2.kundennummer = a.ku
$newarr[] = $arr[$i]['name'];
break;
case "fibu_objekte":
$arr = $this->app->DB->SelectArr("SELECT CONCAT(".$this->app->erp->FormatUCfirst('typ').",'-',id,'-',info) as objekt FROM fibu_objekte WHERE info LIKE '%$term%' LIMIT 20");
$carr = !empty($arr)?count($arr):0;
for($i = 0; $i < $carr; $i++)
$newarr[] = $arr[$i]['objekt'];
break;
case "fibu_belege":
$arr = $this->app->DB->SelectArr("SELECT CONCAT(".$this->app->erp->FormatUCfirst('typ').",'-',id,'-',info) as objekt FROM fibu_objekte WHERE info LIKE '%$term%' AND typ IN ('auftrag','rechnung','gutschrift','verbindlichkeit') LIMIT 20");
$carr = !empty($arr)?count($arr):0;
for($i = 0; $i < $carr; $i++)
$newarr[] = $arr[$i]['objekt'];
break;
case "vpeartikel":
$arr = $this->app->DB->SelectArr("SELECT DISTINCT vpe FROM verkaufspreise WHERE geloescht=0 AND vpe LIKE '%$term%' ORDER by vpe");
$carr = !empty($arr)?count($arr):0;
+69 -1
View File
@@ -848,7 +848,7 @@ class Auftrag extends GenAuftrag
FROM auftrag auf
INNER JOIN auftrag_position ON auf.id = auftrag_position.auftrag
INNER JOIN artikel ON auftrag_position.artikel = artikel.id
WHERE auf.status <> 'abgeschlossen' AND auf.belegnr <> ''
WHERE auf.status NOT IN ('abgeschlossen','storniert') AND auf.belegnr <> ''
ORDER BY urspruengliches_lieferdatum ASC, auf.belegnr ASC, auftrag_position.sort ASC
) a";
@@ -3182,6 +3182,11 @@ class Auftrag extends GenAuftrag
);
}
$this->app->Tpl->Add(
'ZAHLUNGEN',
$this->AuftragZahlung(true)
);
// schaue ob es eine GS zu diesem Auftrag gibt
// schaue ob es eine GS zu diesem Auftrag gibt
//$gutschriftid = $this->app->DB->Select("SELECT id FROM gutschrift WHERE rechnungid='$rechnungid' LIMIT 1");
@@ -3409,7 +3414,47 @@ class Auftrag extends GenAuftrag
<tr><td><b>Lieferadresse:</b><br><br>$lieferadresse</td></tr></table>";
}
/* Build the html output for minidetail containing the payments
* @param bool $return
*
* @return string
*/
function AuftragZahlung($return=false)
{
$id = $this->app->Secure->GetGET('id');
$zahlungen = $this->app->erp->GetZahlungen($id,'auftrag',true);
if (!empty($zahlungen)) {
$et = new EasyTable($this->app);
$et->headings = array('Datum','Beleg','Betrag','W&auml;hrung');
foreach ($zahlungen as $zahlung) {
$row = array(
$zahlung['datum'],
"<a href=\"index.php?module=".$zahlung['doc_typ']."&action=edit&id=".$zahlung['doc_id']."\">
".ucfirst($zahlung['doc_typ'])."
".$zahlung['doc_info']."
</a>",
$zahlung['betrag'],
$zahlung['waehrung']
);
$et->AddRow($row);
}
$salden = $this->app->erp->GetSaldenDokument($id,'auftrag',true);
foreach ($salden as $saldo) {
$row = array(
'',
'<b>Saldo</b>',
"<b>".$saldo['betrag']."</b>",
"<b>".$saldo['waehrung']."</b>"
);
$et->AddRow($row);
}
return($et->DisplayNew('return',""));
}
}
function AuftragZahlungsmail()
{
@@ -6666,6 +6711,29 @@ Die Gesamtsumme stimmt nicht mehr mit urspr&uuml;nglich festgelegten Betrag '.
public function AuftragList()
{
// refresh all open items
$openids = $this->app->DB->SelectArr("SELECT id, gesamtsumme, waehrung from auftrag WHERE status <> 'abgeschlossen'");
foreach ($openids as $openid) {
$saldo = $this->app->erp->GetSaldoDokument($openid['id'],'auftrag');
if (!empty($saldo)) {
if ($saldo['waehrung'] == $openid['waehrung'] && $saldo['betrag'] >= $openid['gesamtsumme']) {
$sql = "UPDATE
auftrag
SET
vorkasse_ok = 1
WHERE id=".$openid['id'];
$this->app->DB->Update($sql);
continue;
}
}
else {
$this->app->DB->Update("UPDATE auftrag SET vorkasse_ok = 0 WHERE id=".$openid['id']);
}
}
if($this->app->Secure->GetPOST('ausfuehren') && $this->app->erp->RechteVorhanden('auftrag', 'edit'))
{
$drucker = $this->app->Secure->GetPOST('seldrucker');
+1 -1
View File
@@ -87,7 +87,7 @@
-->
<div style="background-color:white">
<h2 class="greyh2">{|Zahlungseingang|}</h2>
<h2 class="greyh2">{|Zahlungen|}</h2>
<div style="padding:10px">
[ZAHLUNGEN]
</div>
+204
View File
@@ -0,0 +1,204 @@
<div id="tabs">
<ul>
<li><a href="#tabs-1"></a></li>
</ul>
<!-- Example for multiple tabs
<ul hidden">
<li><a href="#tabs-1">First Tab</a></li>
<li><a href="#tabs-2">Second Tab</a></li>
</ul>
-->
<div id="tabs-1">
[MESSAGE]
<form action="" method="post">
[FORMHANDLEREVENT]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|Einzelbuchung bearbeiten.|}</legend>
<table width="100%" border="0" class="mkTableFormular">
<tr>
<tr>
<td>
{|Von|}:
</td>
<td>
<a href="index.php?module=[VON_TYP]&id=[VON_ID]&action=edit">[VON]</a>
<input hidden type="text" name="von_typ" id="von_typ" value="[VON_TYP]" size="20">
<input hidden type="text" name="von_id" id="von_id" value="[VON_ID]" size="20">
</td>
</tr>
<tr>
<td>
{|Nach|}:
</td>
<td>
<a href="index.php?module=[NACH_TYP]&id=[NACH_ID]&action=edit">[NACH]</a>
<input hidden type="text" name="nach_typ" id="nach_typ" value="[NACH_TYP]" size="20">
<input hidden type="text" name="nach_id" id="nach_id" value="[NACH_ID]" size="20">
</td>
</tr>
<tr>
<td>
{|Betrag|}:
</td>
<td>
<input type="numeric" name="betrag" id="betrag" value="[BETRAG]" size="20">
</td>
</tr>
<tr>
<td>
{|W&auml;hrung|}:
</td>
<td>
<select name="waehrung">[WAEHRUNG]</select>
</td>
</tr>
<tr>
<td>
{|Benutzer|}:
</td>
<td>
[BENUTZER]
</td>
</tr>
<tr>
<td>
{|Datum|}:
</td>
<td>
<input type="text" name="datum" id="datum" value="[DATUM]" size="20">
</td>
</tr>
<tr>
<td>
{|Internebemerkung|}:
</td>
<td>
<textarea type="text" name="internebemerkung" id="internebemerkung" size="20">[INTERNEBEMERKUNG]</textarea>
</td>
</tr>
</table>
</fieldset>
<input type="submit" name="submit" value="Speichern" style="float:right"/>
</div>
</div>
</div>
</div>
[TAB1]
<!-- Example for 2nd row
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|Another legend|}</legend>
<table width="100%" border="0" class="mkTableFormular">
<tr>
<td>
{|Von_typ|}:
</td>
<td>
<input type="text" name="von_typ" id="von_typ" value="[VON_TYP]" size="20">
</td>
</tr>
<tr>
<td>
{|Von_id|}:
</td>
<td>
<input type="text" name="von_id" id="von_id" value="[VON_ID]" size="20">
</td>
</tr>
<tr>
<td>
{|Nach_typ|}:
</td>
<td>
<input type="text" name="nach_typ" id="nach_typ" value="[NACH_TYP]" size="20">
</td>
</tr>
<tr>
<td>
{|Nach_id|}:
</td>
<td>
<input type="text" name="nach_id" id="nach_id" value="[NACH_ID]" size="20">
</td>
</tr>
<tr>
<td>
{|Betrag|}:
</td>
<td>
<input type="text" name="betrag" id="betrag" value="[BETRAG]" size="20">
</td>
</tr>
<tr>
<td>
{|Waehrung|}:
</td>
<td>
<input type="text" name="waehrung" id="waehrung" value="[WAEHRUNG]" size="20">
</td>
</tr>
<tr>
<td>
{|Benutzer|}:
</td>
<td>
<input type="text" name="benutzer" id="benutzer" value="[BENUTZER]" size="20">
</td>
</tr>
<tr>
<td>
{|Zeit|}:
</td>
<td>
<input type="text" name="zeit" id="zeit" value="[ZEIT]" size="20">
</td>
</tr>
<tr>
<td>
{|Internebemerkung|}:
</td>
<td>
<input type="text" name="internebemerkung" id="internebemerkung" value="[INTERNEBEMERKUNG]" size="20">
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div> -->
</form>
</div>
<!-- Example for 2nd tab
<div id="tabs-2">
[MESSAGE]
<form action="" method="post">
[FORMHANDLEREVENT]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|...|}</legend>
<table width="100%" border="0" class="mkTableFormular">
...
</table>
</fieldset>
</div>
</div>
</div>
</div>
<input type="submit" name="submit" value="Speichern" style="float:right"/>
</form>
</div>
-->
</div>
@@ -0,0 +1,105 @@
<form action="" method="post" id="buchungenform">
<div id="tabs">
<ul>
<li><a href="#tabs-1"><!--[TABTEXT]--></a></li>
</ul>
<div id="tabs-1">
[MESSAGE]
[FORMHANDLEREVENT]
<legend>{|Einzelsaldo zuordnen und auf mehrere Gegenbelege oder Sachkonto verbuchen.|}</legend>
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-6 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<table>
<tr>
<td>
"[DOC_ZUORDNUNG]"
</td>
</tr>
<tr>
<td>
Saldo: <u>[DOC_SALDO]</u>
</td>
</tr>
</table>
</fieldset>
</div>
</div>
<div class="col-xs-12 col-md-6 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<table>
<tr>
<td>
Multifilter f&uuml;r "Info" (Trennzeichen ',; ')
</td>
</tr>
<tr>
<td>
<textarea type="text" name="multifilter" id="multifilter" style="width:100%;">[MULTIFILTER]</textarea>
</td>
<td>
<button name="submit" value="multifilter" class="ui-button-icon">{|Filtern|}</button>
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
[TAB1]
<fieldset>
<table>
<legend>Stapelverarbeitung</legend>
<tr>
<td><input type="checkbox" value="1" name="override" form="buchungenform" />&nbsp;Mit Abweichung buchen&nbsp;</td>
</tr>
<tr>
<td><input type="checkbox" value="1" id="autoalle" />&nbsp;alle markieren&nbsp;
<select id="sel_aktion" name="sel_aktion">
<option value="buchen">{|auf Ausgew&auml;hlte buchen|}</option>
<option value="buchen_diff_sachkonto">{|auf Ausgew&auml;hlte buchen, Gegenbeleg auf Sachkonto ausgleichen|}</option>
</select>&nbsp;Sachkonto:
<input type="text" id="sachkonto" name="sachkonto" value="">
<button name="submit" value="BUCHEN" class="ui-button-icon">{|BUCHEN|}</button>
</td>
</tr>
<tr>
<td>
<input type="number" name="abschlag" id="abschlag" value=[ABSCHLAG] />% Abschlag auf Buchungsbetrag</td>
</td>
</tr>
<tr>
<td>
<button name="submit" value="neuberechnen" class="ui-button-icon" style="width:100%;">
{|Buchungen neu berechnen|}
</button>
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<script>
$('#autoalle').on('change',function(){
var wert = $(this).prop('checked');
$('#fibu_buchungen_einzelzuordnen').find('input[type="checkbox"]').prop('checked',wert);
$('#fibu_buchungen_einzelzuordnen').find('input[type="checkbox"]').first().trigger('change');
});
</script>
+62
View File
@@ -0,0 +1,62 @@
<div id="tabs">
<ul>
<li><a href="#tabs-1">Salden</a></li>
<li><a href="#tabs-2">Buchungen</a></li>
</ul>
<div id="tabs-1">
<legend>Salden&uuml;bersicht. Salden m&uuml;ssen &uuml;ber Gegenbuchungen ausgeglichen werden.<br><br></legend>
<form action="" enctype="multipart/form-data" method="POST">
[MESSAGE]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-10 col-md-height">
<div class="inside inside-full-height">
<fieldset>
[TAB1]
</fieldset>
</div>
</div>
<div class="col-xs-12 col-md-2 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<table width="100%" border="0" class="mkTableFormular">
<legend>{|Aktionen|}</legend>
<td><button name="submit" value="neuberechnen" class="ui-button-icon" style="width:100%;">Buchungen neu berechnen</button></td></tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</form>
[TAB1NEXT]
</div>
<div id="tabs-2">
<form action="#tabs-2" enctype="multipart/form-data" method="POST">
[MESSAGE]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-10 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|Einzelbuchungen|}</legend>
[TAB2]
</fieldset>
</div>
</div>
<div class="col-xs-12 col-md-2 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<table width="100%" border="0" class="mkTableFormular">
<legend>{|Aktionen|}</legend>
<td><button name="submit" value="neuberechnen" class="ui-button-icon" style="width:100%;">Buchungen neu berechnen</button></td></tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</form>
[TAB2NEXT]
</div>
</div>
@@ -0,0 +1,79 @@
<div id="tabs">
<ul>
<li><a href="#tabs-1"><!--[TABTEXT]--></a></li>
</ul>
<div id="tabs-1">
[MESSAGE]
[FORMHANDLEREVENT]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|Einzelsalden zuordnen und auf Gegenbelege oder Sachkonto verbuchen.|}</legend>
<div class="filter-box filter-usersave">
<div class="filter-block filter-inline">
<div class="filter-title">{|Filter|}</div>
<ul class="filter-list">
<li class="filter-item">
<label for="vorschlagfilter" class="switch">
<input type="checkbox" id="vorschlagfilter">
<span class="slider round"></span>
</label>
<label for="vorschlagfilter">{|Vorschl&auml;ge|}</label>
</li>
<li class="filter-item">
<label for="checkedfilter" class="switch">
<input type="checkbox" id="checkedfilter">
<span class="slider round"></span>
</label>
<label for="checkedfilter">{|Betrag korrekt|}</label>
</li>
</ul>
</div>
</div>
<form action="" method="post" id="buchungenform">
[TAB1]
</form>
</fieldset>
<fieldset>
<table>
<legend>Stapelverarbeitung</legend>
<tr>
<td><input type="checkbox" value="1" id="autoalle" />&nbsp;alle markieren&nbsp;
<select form="buchungenform" id="sel_aktion" name="sel_aktion">
<option value="vorschlag">{|auf Vorschlag buchen|}</option>
<option value="vorschlag_diff_sachkonto">{|auf Vorschlag buchen, Gegenbeleg auf Sachkonto ausgleichen|}</option>
<option value="sachkonto">{|auf Sachkonto buchen|}</option>
</select>&nbsp;Sachkonto:
<input type="text" form="buchungenform" id="sachkonto" name="sachkonto" value="">
<button name="submit" form="buchungenform" value="BUCHEN" class="ui-button-icon">{|BUCHEN|}</button>
</td>
</tr>
<tr>
<form action="" method="post">
<td>
<button name="submit" value="neuberechnen" class="ui-button-icon" style="width:100%;">
{|Buchungen neu berechnen|}
</button>
</td>
</form>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$('#autoalle').on('change',function(){
var wert = $(this).prop('checked');
$('#fibu_buchungen_zuordnen').find('input[type="checkbox"]').prop('checked',wert);
$('#fibu_buchungen_zuordnen').find('input[type="checkbox"]').first().trigger('change');
});
</script>
+17
View File
@@ -1101,6 +1101,23 @@
</div>
</div>
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-6 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|Finanzbuchhaltung Einstellungen|}</legend>
<table width="100%">
<tr>
<td width="300">Buchungen erzeugen ab Datum:</td><td colspan="3"><input type="text" id= "fibu_buchungen_startdatum" name="fibu_buchungen_startdatum" size="10" value="[FIBU_BUCHUNGEN_STARTDATUM]"></td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
<!--
<fieldset><legend>Finanzbuchhaltung Export Kontenrahmen - Weitere Kostenarten</legend>
<table>
+1 -7
View File
@@ -39,7 +39,7 @@
</div>
<div style="background-color:white">
<h2 class="greyh2">{|Zahlungseingang|}</h2>
<h2 class="greyh2">Buchungen</h2>
<div style="padding:10px">
[ZAHLUNGEN]
</div>
@@ -58,12 +58,6 @@
</div>
</div>
<div style="background-color:white">
<h2 class="greyh2">Deckungsbeitrag</h2>
<div style="padding:10px">
<div class="info">Dieses Modul ist erst ab Version Professional verfügbar</div>
</div>
</div>
</div>
+2 -2
View File
@@ -45,8 +45,8 @@
<input type="checkbox" id="auswahlalle" onchange="alleauswaehlen();" />&nbsp;{|alle markieren|}&nbsp;
<select id="sel_aktion" name="sel_aktion">
<option value="">{|bitte w&auml;hlen|} ...</option>
<option value="erledigtam">{|als erledigt markieren|}</option>
<option value="offen">{|erledigt Markierung entfernen|}</option>
[ALSBEZAHLTMARKIEREN]
<option value="offen">{|als offen markieren|}</option>
<option value="mail">{|per Mail versenden|}</option>
<option value="versendet">{|als versendet markieren|}</option>
<option value="pdf">{|Sammel-PDF|}</option>
+65 -2
View File
@@ -6,7 +6,8 @@
<li><a href="#tabs-3">{|Zeiterfassung|}</a></li>
<li><a href="#tabs-4">{|Wiedervorlagen|}</a></li>
<li><a href="#tabs-5">{|Notizen|}</a></li>
<li><a href="#tabs-6">{|Kontorahmen|}</a></li>
<li><a href="#tabs-6">{|Kontenrahmen|}</a></li>
<li><a href="#tabs-7">{|Kontoauszug|}</a></li>
</ul>
<div id="tabs-1">
@@ -508,7 +509,7 @@
<div class="row">
<div class="col-xs-12 col-sm-1 col-sm-height">
<div class="inside inside-full-height">
<fieldset><legend>{|Kontorahmen|}</legend>
<fieldset><legend>{|Kontenrahmen|}</legend>
<table class="mkTable">
<tr>
<th>Variable</th>
@@ -551,4 +552,66 @@
</div>
</div>
</div>
<div id="tabs-7">
<div class="row">
<div class="col-xs-12 col-sm-1 col-sm-height">
<div class="inside inside-full-height">
<fieldset><legend>{|Kontoauszug|}</legend>
<table class="mkTable">
<tr>
<th>Variable</th>
<th>Beschreibung</th>
<th>Kommentar</th>
</tr>
<tr>
<td>konto</td>
<td>Konto-Kurzbezeichnung</td>
<td></td>
</tr>
<tr>
<td>buchung</td>
<td>Buchungsdatum</td>
<td>Im Format DD.MM.YYYY</td>
</tr>
<tr>
<td>betrag</td>
<td>Betrag</td>
<td></td>
</tr>
<tr>
<td>betrag2</td>
<td>Betrag (wenn z.B. Soll / Haben getrennt)</td>
<td></td>
</tr>
<tr>
<td>waehrung</td>
<td>W&auml;hrung</td>
<td>Muss in den W&auml;hrungen vorhanden sein</td>
</tr>
<tr>
<td>buchungstext</td>
<td>Buchungstext</td>
<td>Wird für die Zuordnung verwendet</td>
</tr>
<tr>
<td>buchungstext2</td>
<td>Buchungstext</td>
<td>Wird für die Zuordnung verwendet</td>
</tr>
<tr>
<td>buchungstext3</td>
<td>Buchungstext</td>
<td>Wird für die Zuordnung verwendet</td>
</tr>
<tr>
<td>buchungstext4</td>
<td>Buchungstext</td>
<td>Wird für die Zuordnung verwendet</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
</div>
@@ -8,7 +8,7 @@
<!--<td width="25%"><a href="index.php?module=shopexport&action=list"><img src="./themes/[THEME]/images/einstellungen/Icons_dunkel_20.gif" border="0" width="30%"></a></td>-->
</tr>
<tr align="center">
<td><a href="index.php?module=importvorlage&action=list">{|Stammdaten|} <br>{|Import|}</a></td>
<td><a href="index.php?module=importvorlage&action=list">{|Daten|} <br>{|Import|}</a></td>
<td><a href="index.php?module=exportvorlage&action=list">{|Stammdaten|} <br>{|Export|}</a></td>
<!--<td><a href="index.php?module=adresse_import&action=list">{|Intranet|}</a></td>-->
<td><a href="index.php?module=shopimport&action=list">{|Import|}<br>({|Online-Shop|})</a></td>
@@ -17,7 +17,7 @@
<tr><td colspan="99">&nbsp;</td></tr>
<tr align="center">
<td width="25%"><a href="index.php?module=exportbelegepositionen&action=export"><img src="./themes/[THEME]/images/einstellungen/Icons_dunkel_1.gif" border="0" width="30%"></a></td>
<td width="25%"><a href="index.php?module=exportbuchhaltung&action=export"><img src="./themes/[THEME]/images/einstellungen/Icons_dunkel_1.gif" border="0" width="30%"></a></td>
<td width="25%"><a href="index.php?module=exportbuchhaltung&action=export"><img src="./themes/[THEME]/images/einstellungen/Icons_dunkel_19.gif" border="0" width="30%"></a></td>
<td width="25%">[BELEGEIMPORTSTART]<a href="index.php?module=belegeimport&action=list"><img src="./themes/[THEME]/images/einstellungen/Icons_dunkel_1.gif" border="0" width="30%"></a>[BELEGEIMPORTEND]</td>
<!--<td width="25%"><a href="index.php?module=shopexport&action=list"><img src="./themes/[THEME]/images/einstellungen/Icons_dunkel_20.gif" border="0" width="30%"></a></td>-->
</tr>
+280 -113
View File
@@ -18,37 +18,66 @@
<legend>{|Einstellungen|}</legend>
<table width="100%">
<tr>
<td width="150">{|Bezeichnung|}:</td>
<td><input type="text" name="bezeichnung" id="bezeichnung" size="40" rule="notempty"
msg="Pflichfeld!" tabindex="2" value="[BEZEICHNUNG]"></td>
<td width="150">
{|Kurzbezeichnung|}:
</td>
<td>
<input type="text" name="kurzbezeichnung" id="kurzbezeichnung" size="40" rule="notempty" msg="Pflichfeld!" tabindex="2" value="[KURZBEZEICHNUNG]" required><i>{|Muss eindeutig sein.|}</i>
</td>
</tr>
<tr>
<td width="150">
{|Bezeichnung|}:
</td>
<td>
<input type="text" name="bezeichnung" id="bezeichnung" size="40" rule="notempty" msg="Pflichfeld!" tabindex="2" value="[BEZEICHNUNG]" required>
</td>
</tr>
<tr>
<td>{|Typ|}:</td>
<td>
{|Typ|}:
</td>
<td>
<!--
<select name="type" id="type">
[TYPE]
</select>
-->
<input type="text" name="type" id="type" size="40" value="konto" required readonly>
</td>
</tr>
<tr>
<td>{|Projekt|}:</td>
<td><input type="text" size="30" name="projekt" id="projekt" value="[PROJEKT]"></td>
<td>
{|Projekt|}:
</td>
<td>
<input type="text" size="30" name="projekt" id="projekt" value="[PROJEKT]">
</td>
</tr>
<tr>
<td>{|Aktiv|}:</td>
<td><input type="checkbox" name="aktiv" id="aktiv" value="1"
[AKTIV]><i>{|Aktiv. Nicht mehr verwendete Konten k&ouml;nnen deaktiviert werden.|}</i>
<td>
{|Aktiv|}:
</td>
<td>
<input type="checkbox" name="aktiv" id="aktiv" value="1"
[AKTIV]><i>{|Aktiv. Nicht mehr verwendete Konten k&ouml;nnen deaktiviert werden.|}</i>
</td>
</tr>
<tr>
<td>{|Keine E-Mail|}:</td>
<td><input type="checkbox" name="keineemail" id="keineemail" value="1"
[KEINEEMAIL]><i>{|Normalerweise wird beim Zahlungseingang eine Mail an den Kunden gesendet. Soll dies unterdr&uuml;ckt werden muss diese Option gesetzt werden.|}</i>
<td>
{|Keine E-Mail|}:
</td>
<td>
<input type="checkbox" name="keineemail" id="keineemail" value="1"
[KEINEEMAIL]><i>{|Normalerweise wird beim Zahlungseingang eine Mail an den Kunden gesendet. Soll dies unterdr&uuml;ckt werden muss diese Option gesetzt werden.|}</i>
</td>
</tr>
<tr>
<td>{|&Auml;nderungen erlauben|}:</td>
<td><input type="checkbox" name="schreibbar" id="schreibbar" value="1"
<td>
{|&Auml;nderungen erlauben|}:
</td>
<td>
<input type="checkbox" name="schreibbar" id="schreibbar" value="1"
[SCHREIBBAR]><i>&nbsp;{|Es d&uuml;rfen nachtr&auml;glich Kontobuchungen ver&auml;ndert werden|}</i>
</td>
</tr>
@@ -66,38 +95,71 @@
<legend>{|Bankverbindung (bei Typ Bank)|}</legend>
<table width="100%">
<tr>
<td width="150">{|Inhaber|}:</td>
<td><input type="text" name="inhaber" id="inhaber" size="40" value="[INHABER]"></td>
<td width="150">{|Inhaber|}:
</td>
<td>
<input type="text" name="inhaber" id="inhaber" size="40" value="[INHABER]">
</td>
<td>
</tr>
<tr>
<td>{|BIC|}:</td>
<td><input type="text" name="swift" id="swift" size="40" value="[SWIFT]"></td>
<td>
{|BIC|}:
</td>
<td>
<input type="text" name="swift" id="swift" size="40" value="[SWIFT]">
</td>
<td>
</tr>
<tr>
<td>{|IBAN|}:</td>
<td><input type="text" name="iban" id="iban" size="40" value="[IBAN]"></td>
<td>
{|IBAN|}:
</td>
<td>
<input type="text" name="iban" id="iban" size="40" value="[IBAN]">
</td>
<td>
</tr>
<tr>
<td>{|BLZ|}:</td>
<td><input type="text" name="blz" id="blz" size="40" value="[BLZ]"></td>
<td>
{|BLZ|}:
</td>
<td>
<input type="text" name="blz" id="blz" size="40" value="[BLZ]">
</td>
<td>
</tr>
<tr>
<td>{|Konto|}:</td>
<td><input type="text" name="konto" id="konto" size="40" value="[KONTO]"></td>
<td>
{|Konto|}:
</td>
<td>
<input type="text" name="konto" id="konto" size="40" value="[KONTO]">
</td>
<td>
</tr>
<tr>
<td>{|Gl&auml;ubiger ID|}:</td>
<td><input type="text" name="glaeubiger" id="glaeubiger" size="40" value="[GLAEUBIGER]"></td>
<td>
{|Gl&auml;ubiger ID|}:
</td>
<td>
<input type="text" name="glaeubiger" id="glaeubiger" size="40" value="[GLAEUBIGER]">
</td>
<td>
</tr>
<tr>
<td>{|Lastschrift|}:</td>
<td><input type="checkbox" name="lastschrift" id="lastschrift" value="1" [LASTSCHRIFT]></td>
<td>
{|Lastschrift|}:
</td>
<td>
<input type="checkbox" name="lastschrift" id="lastschrift" value="1" [LASTSCHRIFT]>
</td>
</tr>
</table>
</fieldset>
@@ -113,9 +175,13 @@
<legend>{|DATEV|}</legend>
<table width="100%">
<tr>
<td width="150">{|Konto|}:</td>
<td><input type="text" name="datevkonto" id="datevkonto" size="40" value="[DATEVKONTO]"></td>
<td width="150">{|Konto|}:
</td>
<td>
<input type="text" name="datevkonto" id="datevkonto" size="40" value="[DATEVKONTO]">
</td>
<td>
</tr>
</table>
</fieldset>
@@ -123,6 +189,7 @@
</div>
</div>
</div>
<!--
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
@@ -131,46 +198,68 @@
<legend>{|CSV-Import|}</legend>
<table width="100%">
<tr>
<td width="150">{|Erste Datenzeile|}:</td>
<td><input type="text" name="importerstezeilenummer" id="importerstezeilenummer" size="15"
value="[IMPORTERSTEZEILENUMMER]">&nbsp;
<i>{|Zeilennummer in der echte Daten stehen (Erste Zeile: 1)|}</i></td>
</tr>
<tr>
<td width="150">{|Kodierung|}:</td>
<td><select name="codierung" id="codierung">[CODIERUNG]</select></td>
</tr>
<tr>
<td width="150">{|Trennzeichen|}:</td>
<td><select name="importtrennzeichen" id="importtrennzeichen">[IMPORTTRENNZEICHEN]</select></td>
</tr>
<tr>
<td width="150">{|Maskierung|}:</td>
<td width="150">{|Erste Datenzeile|}:
</td>
<td>
<input type="text" name="importerstezeilenummer" id="importerstezeilenummer" size="15"
value="[IMPORTERSTEZEILENUMMER]">&nbsp;
<i>{|Zeilennummer in der echte Daten stehen (Erste Zeile: 1)|}</i>
</td>
</tr>
<tr>
<td width="150">{|Kodierung|}:
</td>
<td>
<select name="codierung" id="codierung">[CODIERUNG]</select>
</td>
</tr>
<tr>
<td width="150">{|Trennzeichen|}:
</td>
<td>
<select name="importtrennzeichen" id="importtrennzeichen">[IMPORTTRENNZEICHEN]</select>
</td>
</tr>
<tr>
<td width="150">{|Maskierung|}:
</td>
<td>
<select name="importdatenmaskierung" id="importdatenmaskierung">
[IMPORTDATENMASKIERUNG]
</select>
</td>
</tr>
<tr>
<td width="150">{|Nullbytes entfernen|}:</td>
<td><input type="checkbox" name="importnullbytes" id="importnullbytes" value="1" [IMPORTNULLBYTES]>
<td width="150">{|Nullbytes entfernen|}:
</td>
<td>
<input type="checkbox" name="importnullbytes" id="importnullbytes" value="1" [IMPORTNULLBYTES]>
</td>
</tr>
<tr>
<td width="150">{|Letzte Zeilen ignorieren|}:</td>
<td><input type="text" size="15" name="importletztenzeilenignorieren"
id="importletztenzeilenignorieren" value="[IMPORTLETZTENZEILENIGNORIEREN]"></td>
<td width="150">{|Letzte Zeilen ignorieren|}:
</td>
<td>
<input type="text" size="15" name="importletztenzeilenignorieren"
id="importletztenzeilenignorieren" value="[IMPORTLETZTENZEILENIGNORIEREN]">
</td>
</tr>
</table>
<br><br>
<table>
<tr>
<td width="150">{|Spalte in CSV|}</td>
<td>{|Spalten 1 bis n (Spaltennummer in CSV).|}</tr>
<td width="150">{|Spalte in CSV|}
</td>
<td>
{|Spalten 1 bis n (Spaltennummer in CSV).|}</tr>
<tr>
<td width="150">{|Datum|}:</td>
<td><input type="text" name="importfelddatum" id="importfelddatum" size="15"
<td width="150">{|Datum|}:
</td>
<td>
<input type="text" name="importfelddatum" id="importfelddatum" size="15"
value="[IMPORTFELDDATUM]">
&nbsp;{|Eingabeformat|}:&nbsp;<input type="text" name="importfelddatumformat"
id="importfelddatumformat" size="20"
@@ -179,67 +268,103 @@
id="importfelddatumformatausgabe" size="20"
value="[IMPORTFELDDATUMFORMATAUSGABE]">
<br><i>{|Bsp. 24.12.2016 in CSV entspricht Eingabeformat %1.%2.%3 und Ausgabeformat %3-%2-%1 (Ausgabe muss immer auf diese Format gebracht werden YYYY-MM-DD)|}</i>
</td>
</tr>
<tr>
<td width="150">{|Betrag|}:</td>
<td><input type="text" name="importfeldbetrag" id="importfeldbetrag" size="15"
value="[IMPORTFELDBETRAG]"></td>
</tr>
<tr>
<td width="150">{|Extra Haben u. Soll|}:</td>
<td><input type="checkbox" name="importextrahabensoll" id="importextrahabensoll" value="1" size="15"
[IMPORTEXTRAHABENSOLL] /></td>
</tr>
<tr>
<td></td>
<td width="150">{|Betrag|}:
</td>
<td>
<input type="text" name="importfeldbetrag" id="importfeldbetrag" size="15"
value="[IMPORTFELDBETRAG]">
</td>
</tr>
<tr>
<td width="150">{|Extra Haben u. Soll|}:
</td>
<td>
<input type="checkbox" name="importextrahabensoll" id="importextrahabensoll" value="1" size="15"
[IMPORTEXTRAHABENSOLL] />
</td>
</tr>
<tr>
<td>
</td>
<td>
<table>
<tr>
<td width="150">{|Haben|}:</td>
<td><input type="text" name="importfeldhaben" id="importfeldhaben" size="15"
value="[IMPORTFELDHABEN]"></td>
<td width="150">{|Haben|}:
</td>
<td>
<input type="text" name="importfeldhaben" id="importfeldhaben" size="15"
value="[IMPORTFELDHABEN]">
</td>
</tr>
<tr>
<td width="150">{|Soll|}:</td>
<td><input type="text" name="importfeldsoll" id="importfeldsoll" size="15"
value="[IMPORTFELDSOLL]"></td>
<td width="150">{|Soll|}:
</td>
<td>
<input type="text" name="importfeldsoll" id="importfeldsoll" size="15"
value="[IMPORTFELDSOLL]">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td width="150">{|Buchungstext|}:</td>
<td><input type="text" name="importfeldbuchungstext" id="importfeldbuchungstext" size="15"
<td width="150">{|Buchungstext|}:
</td>
<td>
<input type="text" name="importfeldbuchungstext" id="importfeldbuchungstext" size="15"
value="[IMPORTFELDBUCHUNGSTEXT]">&nbsp;<i> {|Mit + mehre Spalten zusammenf&uuml;gen (aus dem Inhalt wird eine Pr&uuml;fsumme berechnet, daher so eindeutig wie m&ouml;glich machen.)|}</i>
</td>
</tr>
<tr>
<td width="150">{|W&auml;hrung|}:</td>
<td><input type="text" name="importfeldwaehrung" id="importfeldwaehrung" size="15"
value="[IMPORTFELDWAEHRUNG]">&nbsp;<i>{|Ziel: EUR, USD|}</i></td>
</tr>
<tr>
<td width="150">{|Haben/Soll Kennung|}:</td>
<td><input type="text" name="importfeldhabensollkennung" id="importfeldhabensollkennung" size="15"
value="[IMPORTFELDHABENSOLLKENNUNG]">&nbsp;<i>{|Extra Spalte in der steht was der Betrag ist.|}</i>
<td width="150">{|W&auml;hrung|}:
</td>
</tr>
<tr>
<td width="150"></td>
<td>
<input type="text" name="importfeldwaehrung" id="importfeldwaehrung" size="15"
value="[IMPORTFELDWAEHRUNG]">&nbsp;<i>{|Ziel: EUR, USD|}</i>
</td>
</tr>
<tr>
<td width="150">{|Haben/Soll Kennung|}:
</td>
<td>
<input type="text" name="importfeldhabensollkennung" id="importfeldhabensollkennung" size="15"
value="[IMPORTFELDHABENSOLLKENNUNG]">&nbsp;<i>{|Extra Spalte in der steht was der Betrag ist.|}</i>
</td>
</tr>
<tr>
<td width="150">
</td>
<td>
<table>
<tr>
<td width="150">{|Markierung Eingang|}:</td>
<td><input type="text" name="importfeldkennunghaben" id="importfeldkennunghaben" size="15"
value="[IMPORTFELDKENNUNGHABEN]">&nbsp;<i>{|z.B. H oder +|}</i></td>
<td width="150">{|Markierung Eingang|}:
</td>
<td>
<input type="text" name="importfeldkennunghaben" id="importfeldkennunghaben" size="15"
value="[IMPORTFELDKENNUNGHABEN]">&nbsp;<i>{|z.B. H oder +|}</i>
</td>
</tr>
<tr>
<td>{|Markierung Ausgang|}:&nbsp;</td>
<td><input type="text" name="importfeldkennungsoll" id="importfeldkennungsoll" size="15"
value="[IMPORTFELDKENNUNGSOLL]">&nbsp;<i>{|z.B. S oder -|}</i></td>
<td>
{|Markierung Ausgang|}:&nbsp;
</td>
<td>
<input type="text" name="importfeldkennungsoll" id="importfeldkennungsoll" size="15"
value="[IMPORTFELDKENNUNGSOLL]">&nbsp;<i>{|z.B. S oder -|}</i>
</td>
</tr>
</table>
</td>
</tr>
</table>
@@ -256,37 +381,56 @@
<legend>{|Live-Import|}</legend>
<table id="liveimport-table">
<tr>
<td>{|Live-Import aktiv|}:</td>
<td><input type="checkbox" name="liveimport_online" id="liveimport_online" value="1"
[LIVEIMPORT_ONLINE]></td>
<td>
{|Live-Import aktiv|}:
</td>
<td>
<input type="checkbox" name="liveimport_online" id="liveimport_online" value="1"
[LIVEIMPORT_ONLINE]>
</td>
</tr>
<tr>
<td>{|Zeitraum|}:</td>
<td>
{|Zeitraum|}:
</td>
<td>
<select name="importperiode_in_hours" id="importperiode_in_hours">
[IMPORTPERIODE_IN_HOURS]
</select> {|Stunden|}
</td>
</tr>
<tr>
<td>
{|zu Zeiten|}:
</td>
<td>
[SCHEDULER]
</td>
</tr>
[BEFORELIVEIMPORT]
<tr>
<td width="150">{|Zugangsdaten|}:</td>
<td><textarea rows="5" cols="100" name="liveimport" id="liveimport">[LIVEIMPORT]</textarea></td>
<td width="150">{|Zugangsdaten|}:
</td>
<td>
<textarea rows="5" cols="100" name="liveimport" id="liveimport">[LIVEIMPORT]</textarea>
</td>
</tr>
[AFTERLIVEIMPORT]
<tr>
<td>{|Passwort Tresor|}:</td>
<td><input type="button" value="{|Passwort setzen|}"
<td>
{|Passwort Tresor|}:
</td>
<td>
<input type="button" value="{|Passwort setzen|}"
id="setpassword"/>
<i>{|Der Inhalt des Passwort-Tresors kann in der Datenstruktur der Zugangsdaten über die Variable {PASSWORT} genutzt werden.|}</i>
</td>
</tr>
</table>
@@ -316,13 +460,21 @@
<legend>{|Prozessstarter|}</legend>
<table>
<tr>
<td>{|Zahlungseing&auml;nge automatisch abholen|}:</td>
<td><input type="checkbox" name="cronjobaktiv" id="cronjobaktiv" value="1" [CRONJOBAKTIV]></td>
<td>
{|Zahlungseing&auml;nge automatisch abholen|}:
</td>
<td>
<input type="checkbox" name="cronjobaktiv" id="cronjobaktiv" value="1" [CRONJOBAKTIV]>
</td>
</tr>
<tr>
<td>{|Zahlungseing&auml;nge automatisch verbuchen|}:</td>
<td><input type="checkbox" name="cronjobverbuchen" id="cronjobverbuchen" value="1"
[CRONJOBVERBUCHEN]></td>
<td>
{|Zahlungseing&auml;nge automatisch verbuchen|}:
</td>
<td>
<input type="checkbox" name="cronjobverbuchen" id="cronjobverbuchen" value="1"
[CRONJOBVERBUCHEN]>
</td>
</tr>
</table>
</fieldset>
@@ -330,6 +482,7 @@
</div>
</div>
</div>
-->
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
@@ -338,20 +491,32 @@
<legend>{|Startwert für Konto|}</legend>
<table width="100%">
<tr>
<td width="150">{|Summieren|}:</td>
<td><input type="checkbox" name="saldo_summieren" id="saldo_summieren" value="1" [SALDO_SUMMIEREN]>
<td width="150">{|Summieren|}:
</td>
<td>
<input type="checkbox" name="saldo_summieren" id="saldo_summieren" value="1" [SALDO_SUMMIEREN]>
</td>
<td>
</tr>
<tr>
<td width="150">{|Datum Saldo|}:</td>
<td><input type="text" name="saldo_datum" id="saldo_datum" size="40" value="[SALDO_DATUM]"></td>
<td width="150">{|Datum Saldo|}:
</td>
<td>
<input type="text" name="saldo_datum" id="saldo_datum" size="40" value="[SALDO_DATUM]">
</td>
<td>
</tr>
<tr>
<td width="150">{|Betrag Saldo|}:</td>
<td><input type="text" name="saldo_betrag" id="saldo_betrag" size="40" value="[SALDO_BETRAG]"></td>
<td width="150">{|Betrag Saldo|}:
</td>
<td>
<input type="text" name="saldo_betrag" id="saldo_betrag" size="40" value="[SALDO_BETRAG]">
</td>
<td>
</tr>
</table>
</fieldset>
@@ -359,8 +524,7 @@
</div>
</div>
</div>
<input type="hidden" name="save" value="1" />
<input type="submit" value="{|Speichern|}" style="float:right"/>
<input type="submit" name="submit" value="Speichern" style="float:right"/>
</form>
</div>
<!-- tab view schließen -->
@@ -372,8 +536,11 @@
<input type="hidden" id="e_id" value="[ID]"/>
<table width="" cellspacing="0" cellpadding="0">
<tr>
<td width="110"><label for="e_passwort">{|Passwort|}:</label></td>
<td><input type="password" id="e_passwort" name="e_passwort" size="40"/></td>
<td width="110"><label for="e_passwort">{|Passwort|}:</label>
</td>
<td>
<input type="password" id="e_passwort" name="e_passwort" size="40"/>
</td>
</tr>
</table>
</div>
+151
View File
@@ -0,0 +1,151 @@
<div id="tabs">
<ul>
<li><a href="#tabs-1"></a></li>
</ul>
<!-- Example for multiple tabs
<ul hidden">
<li><a href="#tabs-1">First Tab</a></li>
<li><a href="#tabs-2">Second Tab</a></li>
</ul>
-->
<div id="tabs-1">
[MESSAGE]
<form action="" method="post">
[FORMHANDLEREVENT]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|Kontoauszug Eintrag|}</legend>
<table width="100%" border="0" class="mkTableFormular">
<tr>
<td>
{|Konto|}:
</td>
<td>
<input type="text" name="konto" id="konto" value="[KONTO]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Datum|}:
</td>
<td>
<input type="text" name="buchung" id="buchung" value="[BUCHUNG]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Betrag|}:
</td>
<td>
<input type="text" name="soll" id="soll" value="[SOLL]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|W&auml;hrung|}:
</td>
<td>
<input type="text" name="waehrung" id="waehrung" value="[WAEHRUNG]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Fertig|}:
</td>
<td>
<input type="text" name="fertig" id="fertig" value="[FERTIG]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Datev_abgeschlossen|}:
</td>
<td>
<input type="text" name="datev_abgeschlossen" id="datev_abgeschlossen" value="[DATEV_ABGESCHLOSSEN]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Buchungstext|}:
</td>
<td>
<Textarea type="text" name="buchungstext" id="buchungstext" size="20" disabled>[BUCHUNGSTEXT]</textarea>
</td>
</tr>
<tr>
<td>
{|Bearbeiter|}:
</td>
<td>
<input type="text" name="bearbeiter" id="bearbeiter" value="[BEARBEITER]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Internebemerkung|}:
</td>
<td>
<textarea type="text" name="internebemerkung" id="internebemerkung" size="20">[INTERNEBEMERKUNG]</textarea>
</td>
</tr>
<tr>
<td>
{|Importfehler|}:
</td>
<td>
<input type="text" name="importfehler" id="importfehler" value="[IMPORTFEHLER]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Klaerfall|}:
</td>
<td>
<input type="text" name="klaerfall" id="klaerfall" value="[KLAERFALL]" size="20" disabled>
</td>
</tr>
<tr>
<td>
{|Klaergrund|}:
</td>
<td>
<input type="text" name="klaergrund" id="klaergrund" value="[KLAERGRUND]" size="20" disabled>
</td>
</tr>
</table>
</fieldset>
</div>
</div>
</div>
</div>
<input type="submit" name="submit" value="Speichern" style="float:right"/>
</form>
</div>
<!-- Example for 2nd tab
<div id="tabs-2">
[MESSAGE]
<form action="" method="post">
[FORMHANDLEREVENT]
<div class="row">
<div class="row-height">
<div class="col-xs-12 col-md-12 col-md-height">
<div class="inside inside-full-height">
<fieldset>
<legend>{|...|}</legend>
<table width="100%" border="0" class="mkTableFormular">
...
</table>
</fieldset>
</div>
</div>
</div>
</div>
<input type="submit" name="submit" value="Speichern" style="float:right"/>
</form>
</div>
-->
</div>
@@ -0,0 +1,14 @@
<div id="tabs">
<ul>
<li><a href="#tabs-1">[TABTEXT1]</a></li>
</ul>
<div id="tabs-1">
<form action="#tabs-1" id="frmauto" name="frmauto" method="post">
[MESSAGE]
<legend>Kontoausz&uuml;ge bitte &uuml;ber Importzentrale importieren.</legend>
[TAB1]
</form>
</div>
</div>
+46
View File
@@ -0,0 +1,46 @@
<div id="tabs">
<ul>
<li><a href="#tabs-1">[TABTEXT1]</a></li>
</ul>
<div id="tabs-1">
<form action="#tabs-1" id="frmauto" name="frmauto" method="post">
[MESSAGE]
<legend>[INFO]</legend>
<div class="filter-box filter-usersave">
<div class="filter-block filter-inline">
<div class="filter-title">{|Filter|}</div>
<ul class="filter-list">
[STATUSFILTER]
<li class="filter-item">
<label for="importfehler" class="switch">
<input type="checkbox" id="importfehler" />
<span class="slider round"></span>
</label>
<label for="meinetickets">{|Inkl. Importfehler|}</label>
</li>
</ul>
</div>
</div>
[TAB1]
<fieldset>
<table>
<legend>Stapelverarbeitung</legend>
<tr>
<td><input type="checkbox" value="1" id="autoalle" />&nbsp;alle markieren&nbsp;</td>
<td><input type="submit" class="btnBlue" name="ausfuehren" value="{|Importfehler|}" /></td>
</tr>
</table>
</fieldset>
</form>
</div>
</div>
<script>
$('#autoalle').on('change',function(){
var wert = $(this).prop('checked');
$('#kontoauszuege_list').find('input[type="checkbox"]').prop('checked',wert);
$('#kontoauszuege_list').find('input[type="checkbox"]').first().trigger('change');
});
</script>
+10 -13
View File
@@ -44,7 +44,7 @@
</div>
<div style="background-color:white">
<h2 class="greyh2">Zahlungseingang</h2>
<h2 class="greyh2">Buchungen</h2>
<div style="padding:10px">
[ZAHLUNGEN]
</div>
@@ -69,15 +69,12 @@
[PDFARCHIV]
</div>
</div>
<div style="background-color:white">
<h2 class="greyh2">Deckungsbeitrag</h2>
<div style="padding:10px">
<div class="info">Dieses Modul ist erst ab Version Professional verfügbar</div>
</div>
</div>
</div>
<!--
<div style="background-color:white">
<h2 class="greyh2">Deckungsbeitrag</h2>
<div style="padding:10px">
<div class="info">Dieses Modul ist erst ab Version Professional verfügbar</div>
</div>
</div>
</div>
-->
File diff suppressed because it is too large Load Diff
+12 -1
View File
@@ -1043,7 +1043,7 @@ class Firmendaten {
'arbeitsnachweis_header','arbeitsnachweis_footer','provisionsgutschrift_header','provisionsgutschrift_footer','proformarechnung_header','proformarechnung_footer','eu_lieferung_vermerk','export_lieferung_vermerk'
,'wareneingang_kamera_waage','layout_iconbar','passwort','host','port','mailssl','signatur','email','absendername','bcc1','bcc2','bcc3'
,'firmenfarbe','name','strasse','plz','ort','steuernummer','projekt','steuer_positionen_export','tabsnavigationfarbe','tabsnavigationfarbeschrift'
,"buchhaltung_berater","buchhaltung_mandant","buchhaltung_wj_beginn","buchhaltung_sachkontenlaenge"
,"buchhaltung_berater","buchhaltung_mandant","buchhaltung_wj_beginn","buchhaltung_sachkontenlaenge", "fibu_buchungen_startdatum"
);
if(isset($sql2a)){
@@ -1379,6 +1379,10 @@ class Firmendaten {
}
$this->app->YUI->AutoComplete('steuersatz_normal','steuersatz',1);
$this->app->YUI->AutoComplete('steuersatz_ermaessigt','steuersatz',1);
$this->app->YUI->DatePicker('fibu_buchungen_startdatum');
$this->app->Tpl->Parse('PAGE','firmendaten.tpl');
}
@@ -1842,6 +1846,11 @@ class Firmendaten {
if(!empty($data[0]['taxfromdoctypesettings'])) {
$this->app->Tpl->Set('OPTIONTAXFROMDOCTYPESETTINGS', ' selected="selected" ');
}
// Fibu
$this->app->Tpl->Set('FIBU_BUCHUNGEN_STARTDATUM', $this->app->erp->ReplaceDatum(false,$data[0]['fibu_buchungen_startdatum'],false));
}
}
@@ -2282,6 +2291,8 @@ class Firmendaten {
$data['buchhaltung_wj_beginn'] = ($this->app->Secure->POST["buchhaltung_wj_beginn"]);
$data['buchhaltung_sachkontenlaenge'] = ($this->app->Secure->POST["buchhaltung_sachkontenlaenge"]);
$data['fibu_buchungen_startdatum'] = $this->app->erp->ReplaceDatum(true,$this->app->Secure->POST["fibu_buchungen_startdatum"],false);
return $data;
}
+115 -112
View File
@@ -620,6 +620,8 @@ class Gutschrift extends GenGutschrift
$tmp3->DisplayNew('PDFARCHIV','Men&uuml;','noAction');
}
$this->app->Tpl->Add('ZAHLUNGEN',$this->GutschriftZahlung(true));
if($parsetarget=='') {
$this->app->Tpl->Output('gutschrift_minidetail.tpl');
$this->app->ExitXentral();
@@ -648,6 +650,7 @@ class Gutschrift extends GenGutschrift
/**
* Build the html output for minidetail containing the payments
* @param bool $return
*
* @return string
@@ -656,102 +659,37 @@ class Gutschrift extends GenGutschrift
{
$id = $this->app->Secure->GetGET('id');
$gutschriftArr = $this->app->DB->SelectArr(
"SELECT DATE_FORMAT(datum,'%d.%m.%Y') as datum, belegnr, soll, waehrung, rechnungid
FROM gutschrift WHERE id='$id' LIMIT 1"
);
$waehrung = empty($gutschriftArr)?'EUR':$gutschriftArr[0]['waehrung'];
if(!$waehrung) {
$waehrung = 'EUR';
}
$zahlungen = $this->app->erp->GetZahlungen($id,'gutschrift');
if (!empty($zahlungen)) {
$et = new EasyTable($this->app);
$rechnungid = empty($gutschriftArr)?0: $gutschriftArr[0]['rechnungid'];
$et->headings = array('Datum','Beleg','Betrag','W&auml;hrung');
$auftragid = $rechnungid <= 0?0:$this->app->DB->Select(
sprintf(
'SELECT `auftragid` FROM `rechnung` WHERE `id` = %d LIMIT 1',
$rechnungid
)
);
$eingang ="<tr><td colspan=\"3\"><b>Zahlungen</b></td></tr>";
foreach ($zahlungen as $zahlung) {
$row = array(
$zahlung['datum'],
"<a href=\"index.php?module=".$zahlung['doc_typ']."&action=edit&id=".$zahlung['doc_id']."\">
".ucfirst($zahlung['doc_typ'])."
".$zahlung['doc_info']."
</a>",
$zahlung['betrag'],
$zahlung['waehrung']
);
$et->AddRow($row);
}
$eingang .="<tr><td class=auftrag_cell>".$gutschriftArr[0]['datum']
."</td><td class=auftrag_cell>GS ".$gutschriftArr[0]['belegnr']
."</td><td class=auftrag_cell align=right>".$this->app->erp->EUR($gutschriftArr[0]['soll'])
." $waehrung</td></tr>";
$eingangArr = $this->app->DB->SelectArr(
"SELECT ko.bezeichnung as konto, DATE_FORMAT(ke.datum,'%d.%m.%Y') as datum, k.id as kontoauszuege,
ke.betrag as betrag, k.id as zeile,k.waehrung
FROM kontoauszuege_zahlungseingang ke
LEFT JOIN kontoauszuege k ON ke.kontoauszuege=k.id
LEFT JOIN konten ko ON k.konto=ko.id
WHERE (ke.objekt='gutschrift' AND ke.parameter='$id')
OR (ke.objekt='auftrag' AND ke.parameter='$auftragid' AND ke.parameter>0)
OR (ke.objekt='rechnung' AND ke.parameter='$rechnungid' AND ke.parameter>0)"
);
$ceingangArr = empty($eingangArr)?0:(!empty($eingangArr)?count($eingangArr):0);
for($i=0;$i<$ceingangArr;$i++) {
$waehrung = 'EUR';
if($eingangArr[$i]['waehrung']) {
$waehrung = $eingangArr[$i]['waehrung'];
}
$eingang .="<tr><td class=auftrag_cell>".$eingangArr[$i]['datum']
."</td><td class=auftrag_cell>".$eingangArr[$i]['konto']
."&nbsp;(<a href=\"index.php?module=zahlungseingang&action=editzeile&id="
.$eingangArr[$i]['zeile']."\">zur Buchung</a>)</td><td class=auftrag_cell align=right>"
.$this->app->erp->EUR($eingangArr[$i]['betrag'])
." $waehrung</td></tr>";
}
// gutschriften zu dieser rechnung anzeigen
/*
$gutschriften = $this->app->DB->SelectArr("SELECT belegnr, DATE_FORMAT(datum,'%d.%m.%Y') as datum,soll FROM gutschrift WHERE rechnungid='$id'");
for($i=0;$i<(!empty($gutschriften)?count($gutschriften):0);$i++)
$eingang .="<tr><td class=auftrag_cell>".$gutschriften[$i]['datum']."</td><td class=auftrag_cell>GS ".$gutschriften[$i]['belegnr']."</td><td class=auftrag_cell align=right>".$this->app->erp->EUR($gutschriften[$i]['soll'])." EUR</td></tr>";
*/
$ausgang = '';
$ausgangArr = $this->app->DB->SelectArr(
"SELECT ko.bezeichnung as konto, DATE_FORMAT(ke.datum,'%d.%m.%Y') as datum, ke.betrag as betrag,
k.id as zeile,k.waehrung
FROM kontoauszuege_zahlungsausgang ke
LEFT JOIN kontoauszuege k ON ke.kontoauszuege=k.id
LEFT JOIN konten ko ON k.konto=ko.id
WHERE (ke.objekt='gutschrift' AND ke.parameter='$id')
OR (ke.objekt='rechnung' AND ke.parameter='$rechnungid' AND ke.parameter>0)
OR (ke.objekt='auftrag' AND ke.parameter='$auftragid' AND ke.parameter>0)"
);
$cAusgangArr = empty($ausgangArr)?0:(!empty($ausgangArr)?count($ausgangArr):0);
for($i=0;$i<$cAusgangArr;$i++) {
$waehrung = 'EUR';
if($ausgangArr[$i]['waehrung']) {
$waehrung = $ausgangArr[$i]['waehrung'];
}
$ausgang .="<tr><td class=auftrag_cell>".$ausgangArr[$i]['datum']."</td><td class=auftrag_cell>"
.$ausgangArr[$i]['konto']."&nbsp;(<a href=\"index.php?module=zahlungseingang&action=editzeile&id="
.$ausgangArr[$i]['zeile']."\">zur Buchung</a>)</td><td class=auftrag_cell align=right>"
.$this->app->erp->EUR($ausgangArr[$i]['betrag'])
." $waehrung</td></tr>";
}
$saldo = $this->app->erp->EUR($this->app->erp->GutschriftSaldo($id));
if($saldo < 0) {
$saldo = "<b style=\"color:red\">$saldo</b>";
}
$waehrung = $this->app->DB->Select("SELECT waehrung FROM gutschrift WHERE id = '$id' LIMIT 1");
if(!$waehrung) {
$waehrung = 'EUR';
}
$ausgang .="<tr><td class=auftrag_cell></td><td class=auftrag_cell align=right>Saldo</td><td class=auftrag_cell align=right>$saldo $waehrung</td></tr>";
if($return) {
return "<table width=100% border=0 class=auftrag_cell cellpadding=0 cellspacing=0>".$eingang." ".$ausgang."</table>";
}
$salden = $this->app->erp->GetSaldenDokument($id,'gutschrift');
foreach ($salden as $saldo) {
$row = array(
'',
'<b>Saldo</b>',
"<b>".$saldo['betrag']."</b>",
"<b>".$saldo['waehrung']."</b>"
);
$et->AddRow($row);
}
return($et->DisplayNew('return',""));
}
}
@@ -774,17 +712,32 @@ class Gutschrift extends GenGutschrift
$showDefault = true;
$this->app->Tpl->Set('TABTEXT','Freigabe');
$this->app->erp->GutschriftNeuberechnen($id);
$this->app->erp->CheckVertrieb($id,'gutschrift');
$this->app->erp->CheckBearbeiter($id,'gutschrift');
$doctype = 'gutschrift';
$sql = "SELECT belegnr, rechnungid FROM gutschrift WHERE id='$id' LIMIT 1";
$result = $this->app->DB->SelectArr($sql);
$belegnr = $result[0]['belegnr'];
$rechnungid = $result[0]['rechnungid'];
$name = $this->app->DB->Select("SELECT a.name FROM gutschrift b LEFT JOIN adresse a ON a.id=b.adresse WHERE b.id='$id' LIMIT 1");
$summe = $this->app->DB->Select("SELECT soll FROM gutschrift WHERE id='$id' LIMIT 1");
$waehrung = $this->app->DB->Select("SELECT waehrung FROM gutschrift_position WHERE gutschrift='$id' LIMIT 1");
if(empty($intern)){
$this->app->erp->RunHook('beleg_freigabe', 4, $doctype, $id, $allowedFrm, $showDefault);
}
if($allowedFrm && $freigabe==$id) {
$belegnr = $this->app->DB->Select("SELECT belegnr FROM gutschrift WHERE id='$id' LIMIT 1");
if($allowedFrm && $freigabe==$id) {
if($belegnr=='') {
$this->app->erp->BelegFreigabe('gutschrift',$id);
// Create fibu_buchung
$gegen_rechnung = $this->app->Secure->GetGET('gegen_rechnung');
if ($gegen_rechnung && $rechnungid > 0) {
$this->app->erp->fibu_buchungen_buchen('gutschrift', $id, 'rechnung', $rechnungid, -$summe, $waehrung, date("Y-m-d"), 'Verrechnung');
}
if($intern) {
return 1;
}
@@ -797,15 +750,17 @@ class Gutschrift extends GenGutschrift
$msg = $this->app->erp->base64_url_encode("<div class=\"error\">Die Gutschrift war bereits freigegeben!</div>");
$this->app->Location->execute("index.php?module=gutschrift&action=edit&id=$id&msg=$msg");
}
if($showDefault){
$name = $this->app->DB->Select("SELECT a.name FROM gutschrift b LEFT JOIN adresse a ON a.id=b.adresse WHERE b.id='$id' LIMIT 1");
$summe = $this->app->DB->Select("SELECT soll FROM gutschrift WHERE id='$id' LIMIT 1");
$waehrung = $this->app->DB->Select("SELECT waehrung FROM gutschrift_position
WHERE gutschrift='$id' LIMIT 1");
if($showDefault){
if ($rechnungid > 0) {
$input_html = "<input type=\"button\" value=\"Freigabe ohne Rechnung\" onclick=\"window.location.href='index.php?module=gutschrift&action=freigabe&id=$id&freigabe=$id&gegen_rechnung=0'\">"
."<input type=\"button\" value=\"Freigabe gegen Rechnung\" onclick=\"window.location.href='index.php?module=gutschrift&action=freigabe&id=$id&freigabe=$id&gegen_rechnung=1'\">";
} else {
$input_html = "<input type=\"button\" value=\"Freigabe Rechnung\" onclick=\"window.location.href='index.php?module=gutschrift&action=freigabe&id=$id&freigabe=$id'\">";
}
$this->app->Tpl->Set('TAB1', "<div class=\"info\">Soll die Gutschrift an <b>$name</b> im Wert von <b>$summe $waehrung</b>
jetzt freigegeben werden? <input type=\"button\" value=\"Freigabe\" onclick=\"window.location.href='index.php?module=gutschrift&action=freigabe&id=$id&freigabe=$id'\">
</div>");
jetzt freigegeben werden? ".
$input_html.
"</div>");
}
$this->GutschriftMenu();
$this->app->Tpl->Parse('PAGE','tabview.tpl');
@@ -1176,7 +1131,6 @@ class Gutschrift extends GenGutschrift
$this->app->erp->CheckBearbeiter($id,"gutschrift");
$this->app->erp->CheckBuchhaltung($id,"gutschrift");
$this->app->erp->GutschriftNeuberechnen($id);
$this->app->erp->DisableVerband();
@@ -1185,14 +1139,11 @@ class Gutschrift extends GenGutschrift
$this->app->Tpl->Set('ICONMENU',$this->GutschriftIconMenu($id));
$this->app->Tpl->Set('ICONMENU2',$this->GutschriftIconMenu($id,2));
$belegnr = $this->app->DB->Select("SELECT belegnr FROM gutschrift WHERE id='$id' LIMIT 1");
$nummer = $this->app->DB->Select("SELECT belegnr FROM gutschrift WHERE id='$id' LIMIT 1");
$kundennummer = $this->app->DB->Select("SELECT kundennummer FROM gutschrift WHERE id='$id' LIMIT 1");
$adresse = $this->app->DB->Select("SELECT adresse FROM gutschrift WHERE id='$id' LIMIT 1");
$status= $this->app->DB->Select("SELECT status FROM gutschrift WHERE id='$id' LIMIT 1");
$schreibschutz= $this->app->DB->Select("SELECT schreibschutz FROM gutschrift WHERE id='$id' LIMIT 1");
if($status !== 'angelegt' && $status !== 'angelegta' && $status !== 'a')
@@ -1241,7 +1192,12 @@ class Gutschrift extends GenGutschrift
if($zahlungsweise=="einzugsermaechtigung" || $zahlungsweise=="lastschrift") $this->app->Tpl->Set('EINZUGSERMAECHTIGUNG',"");
if($zahlungsweise=="vorkasse" || $zahlungsweise=="kreditkarte" || $zahlungsweise=="paypal" || $zahlungsweise=="bar") $this->app->Tpl->Set('VORKASSE',"");
$zahlungsinfo = $this->app->DB->SelectArr("SELECT zahlungsstatus, ".$this->app->erp->FormatMenge('soll*(-1)',2)." as betrag FROM gutschrift WHERE id='$id' LIMIT 1");
$this->app->Tpl->Set('ZAHLUNGSSTATUS_DB',$zahlungsinfo[0]['zahlungsstatus']);
$this->app->Tpl->Set('SOLL',$zahlungsinfo[0]['betrag']);
$ist = $this->app->erp->EUR($this->app->erp->GetSaldoDokument($id,'gutschrift')['betrag']);
$this->app->Tpl->Set('ISTDB',$ist);
if($schreibschutz=="1" && $this->app->erp->RechteVorhanden("gutschrift","schreibschutz"))
{
@@ -1249,11 +1205,24 @@ class Gutschrift extends GenGutschrift
// $this->app->erp->CommonReadonly();
}
if($schreibschutz=="1")
$this->app->erp->CommonReadonly();
if($schreibschutz=="1") {
$this->app->erp->CommonReadonly();
}
if($schreibschutz=='1' && $this->app->erp->RechteVorhanden('gutschrift','edit'))
{
$this->app->erp->RemoveReadonly('zahlungsstatus');
if ($aktion = $this->app->Secure->GetPOST('speichern') == 'Speichern') {
$zahlungsstatus = $this->app->Secure->GetPOST('zahlungsstatus');
$this->app->DB->Update("UPDATE gutschrift SET zahlungsstatus='".$zahlungsstatus."' WHERE id='$id' LIMIT 1");
}
}
$rechnungid = $this->app->DB->Select("SELECT rechnungid FROM gutschrift WHERE id='$id' LIMIT 1");
$rechnungid = $this->app->DB->Select("SELECT id FROM rechnung WHERE id='$rechnungid' AND belegnr!='' LIMIT 1");
$alle_gutschriften = $this->app->DB->SelectArr("SELECT id,belegnr FROM gutschrift WHERE rechnungid='$rechnungid' AND rechnungid>0");
if (!is_null($alle_gutschriften)) {
@@ -1445,6 +1414,8 @@ class Gutschrift extends GenGutschrift
{
$this->app->Tpl->Set('UEBERSCHRIFT', 'Gutschriften');
$this->app->DB->Update("UPDATE gutschrift SET zahlungsstatus='offen' WHERE zahlungsstatus=''");
if($this->app->Secure->GetPOST('ausfuehren') && $this->app->erp->RechteVorhanden('gutschrift', 'edit')) {
$drucker = $this->app->Secure->GetPOST('seldrucker');
$aktion = $this->app->Secure->GetPOST('sel_aktion');
@@ -1463,7 +1434,13 @@ class Gutschrift extends GenGutschrift
$ids = array_unique($ids);
switch($aktion) {
case 'erledigtam':
case 'bezahlt':
$this->app->DB->Update("UPDATE gutschrift SET zahlungsstatus='bezahlt' WHERE id IN (".implode(', ',$ids).')');
break;
case 'offen':
$this->app->DB->Update("UPDATE gutschrift SET zahlungsstatus='offen' WHERE id IN (".implode(', ',$ids).')');
break;
/* case 'erledigtam':
if(!empty($ids)){
$this->app->DB->Update(
sprintf(
@@ -1488,7 +1465,7 @@ class Gutschrift extends GenGutschrift
)
);
}
break;
break;*/
case 'mail':
$returnOrders = empty($ids)?[]:$this->app->DB->SelectArr(
sprintf(
@@ -1682,6 +1659,28 @@ class Gutschrift extends GenGutschrift
}
}
// refresh all open items
$openids = $this->app->DB->SelectArr("SELECT id, waehrung from gutschrift WHERE zahlungsstatus != 'bezahlt'");
foreach ($openids as $openid) {
$saldo = $this->app->erp->GetSaldoDokument($openid['id'],'gutschrift');
if (!empty($saldo)) {
if ($saldo['waehrung'] == $openid['waehrung']) {
$sql = "UPDATE
gutschrift
SET
ist = ".$saldo['betrag']."+soll,
zahlungsstatus = IF(".$saldo['betrag']." = 0,'bezahlt','offen')
WHERE id=".$openid['id'];
$this->app->DB->Update($sql);
}
}
else {
$this->app->DB->Update("UPDATE gutschrift SET ist = null WHERE id=".$openid['id']);
}
}
$backurl = $this->app->Secure->GetGET('backurl');
$backurl = $this->app->erp->base64_url_decode($backurl);
@@ -1770,6 +1769,10 @@ class Gutschrift extends GenGutschrift
$this->app->YUI->TableSearch('TAB1','gutschriften');
$this->app->YUI->TableSearch('TAB3','gutschrifteninbearbeitung');
if($this->app->erp->RechteVorhanden('rechnung', 'manuellbezahltmarkiert')){
$this->app->Tpl->Set('ALSBEZAHLTMARKIEREN', '<option value="bezahlt">{|als bezahlt markieren|}</option>');
}
$this->app->Tpl->Set(
'SELDRUCKER',
$this->app->erp->GetSelectDrucker($this->app->User->GetParameter('rechnung_list_drucker'))
+102 -14
View File
@@ -1030,7 +1030,7 @@ class Importvorlage extends GenImportvorlage {
if (!move_uploaded_file($_FILES['userfile']['tmp_name'], $stueckliste_csv)) {
//$importfilename = $_FILES['userfile']['name'];
$msg = $this->app->erp->base64_url_encode("<div class=\"error\">Die Datei konnte nicht ge&ouml;ffnet werden. Eventuell ist die Datei zu gro&szlig; oder die Schreibrechte stimmen nicht!</div> ");
$msg = $this->app->erp->base64_url_encode("<div class=\"error\">Die Datei '".$stueckliste_csv."' konnte nicht ge&ouml;ffnet werden. Eventuell ist die Datei zu gro&szlig; oder die Schreibrechte stimmen nicht!</div> ");
$this->app->Location->execute("index.php?module=importvorlage&action=import&id=$id&msg=$msg");
}
@@ -1419,7 +1419,7 @@ class Importvorlage extends GenImportvorlage {
$zeitstempel = time();
$number_of_rows = empty($tmp['cmd'])?0:count($tmp['cmd']);
$number_of_rows = $number_of_rows + 2;
// $number_of_rows = $number_of_rows + 2; // ?!?!
if($isCronjob) {
$this->app->DB->Update(
@@ -5079,6 +5079,92 @@ class Importvorlage extends GenImportvorlage {
}
break;
case 'kontoauszug':
$allowed_fields = array('konto','buchung','betrag','betrag2','waehrung','buchungstext','buchungstext2','buchungstext3','buchungstext4');
$error = false;
// Create a row dataset (without checked and cmd)
$update_sql = "";
$row = array();
$comma = "";
foreach ($tmp as $key => $value) {
if ($key != 'cmd' && $key != 'checked') {
if (in_array($key,$allowed_fields)) {
$row[$key] = $value[$i];
$comma = ", ";
} else {
$msg .= "Feld nicht korrekt: ".$key.".<br>";
$error = true;
}
}
}
if (!$error) {
// Collect texts
$buchungstext = "";
$comma = "";
foreach ($row as $key => $value) {
if (str_starts_with($key,'buchungstext')) {
if (!empty($value)) {
$buchungstext .= $comma.$value;
$comma = ", ";
}
unset($row[$key]);
}
}
$row['buchungstext'] = $buchungstext;
$row['soll'] = $row['betrag'];
unset($row['betrag']);
if (empty($row['soll'])) {
$row['soll'] = $row['betrag2'];
}
unset($row['betrag2']);
$row['soll'] = $this->app->erp->ReplaceBetrag(true,$row['soll']);
$row['buchung'] = $this->app->erp->ReplaceDatum(true,$row['buchung'],false);
// Calculate hash
$hash_fields = array('buchung','soll','waehrung','buchungstext');
$hash_text = "";
foreach($hash_fields as $hash_field) {
$hash_text .= $row[$hash_field];
}
$row['pruefsumme'] = md5($hash_text);
$sql = "SELECT id FROM konten WHERE kurzbezeichnung ='".$row['konto']."' LIMIT 1";
$kontoid = $this->app->DB->SelectArr($sql);
if (!empty($kontoid)) {
$row['konto'] = $kontoid[0]['id'];
$row['importdatum'] = date("Y-m-d H:i:s");
$sql = "SELECT pruefsumme FROM kontoauszuege WHERE pruefsumme='".$row['pruefsumme']."' AND konto ='".$row['konto']."' AND importfehler IS NULL";
$result = $this->app->DB->SelectArr($sql);
if (!empty($result)) {
$msg .= "Doppelter Eintrag (nicht importiert): ".$row['buchungstext']."<br>";
} else {
$sql = "INSERT INTO kontoauszuege (".
implode(", ",array_keys($row)).
") VALUES ('".
implode("', '",array_values($row)).
"')";
$result = $this->app->DB->Update($sql);
}
} else {
$msg .= "Konto nicht gefunden: ".$row['konto'].".<br>";
}
}
break;
}
// HERE END OF PROCESSING THE ROWS switch($ziel);
@@ -5106,20 +5192,22 @@ class Importvorlage extends GenImportvorlage {
if(empty($importMasterData) || $importMasterData['status'] === 'cancelled') {
break;
}
}
} // Loop
if($return) {
if($returnids) {
return $ids;
}
return $number_of_rows;
}
if($return) {
if($returnids) {
return $ids;
}
return $number_of_rows;
}
if($ziel==='zeiterfassung' || $ziel==='wiedervorlage' || $ziel==='notizen') {
$msg=$this->app->erp->base64_url_encode("<div class=\"info\">Import durchgef&uuml;hrt.</div>");
$this->app->Location->execute("index.php?module=importvorlage&action=import&id=$id&msg=$msg");
}
$msg=$this->app->erp->base64_url_encode("<div class=\"info\">Import durchgef&uuml;hrt.</div>");
$this->app->Location->execute("index.php?module=importvorlage&action=import&id=$id&msg=$msg");
if (empty($msg)) {
$msg=$this->app->erp->base64_url_encode("<div class=\"info\">Import durchgef&uuml;hrt.</div>");
$this->app->Location->execute("index.php?module=importvorlage&action=import&id=$id&msg=$msg");
} else {
$msg=$this->app->erp->base64_url_encode("<div class=\"error\">".$msg."</div>");
$this->app->Location->execute("index.php?module=importvorlage&action=import&id=$id&msg=$msg");
}
}
/**
+349
View File
@@ -0,0 +1,349 @@
<?php
/*
* Copyright (c) 2022 OpenXE project
*/
use Xentral\Components\Database\Exception\QueryFailureException;
class Konten {
function __construct($app, $intern = false) {
$this->app = $app;
if ($intern)
return;
$this->app->ActionHandlerInit($this);
$this->app->ActionHandler("list", "konten_list");
$this->app->ActionHandler("create", "konten_edit"); // This automatically adds a "New" button
$this->app->ActionHandler("edit", "konten_edit");
$this->app->ActionHandler("delete", "konten_delete");
$this->app->DefaultActionHandler("list");
$this->app->ActionHandlerListen($app);
}
public function Install() {
/* Fill out manually later */
}
static function TableSearch(&$app, $name, $erlaubtevars) {
switch ($name) {
case "konten_list":
$allowed['konten_list'] = array('list');
$heading = array('','','Bezeichnung', 'Kurzbezeichnung', 'Typ', 'Projekt', 'Aktiv','Men&uuml;');
$width = array('1%','1%','10%'); // Fill out manually later
// columns that are aligned right (numbers etc)
// $alignright = array(4,5,6,7,8);
$findcols = array('k.id','k.id','k.bezeichnung', 'k.kurzbezeichnung', 'k.type', 'p.abkuerzung', ' k.aktiv','k.id');
$searchsql = array('k.bezeichnung', 'k.kurzbezeichnung', 'k.datevkonto', 'k.blz', 'k.konto', 'k.swift', 'k.iban', 'k.inhaber', 'k.firma','p.abkuerzung');
$defaultorder = 1;
$defaultorderdesc = 0;
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',k.id,'\" />') AS `auswahl`";
$menu = "<table cellpadding=0 cellspacing=0><tr><td nowrap>" . "<a href=\"index.php?module=konten&action=edit&id=%value%\"><img src=\"./themes/{$app->Conf->WFconf['defaulttheme']}/images/edit.svg\" border=\"0\"></a>&nbsp;<a href=\"#\" onclick=DeleteDialog(\"index.php?module=konten&action=delete&id=%value%\");>" . "<img src=\"themes/{$app->Conf->WFconf['defaulttheme']}/images/delete.svg\" border=\"0\"></a>" . "</td></tr></table>";
$sql = "SELECT SQL_CALC_FOUND_ROWS
k.id,
$dropnbox,
k.bezeichnung,
k.kurzbezeichnung,
k.type,
p.abkuerzung,
k.aktiv,
k.id
FROM
konten k
LEFT JOIN
projekt p
ON
p.id = k.projekt ";
$where = " k.aktiv = 1 ";
// Toggle filters
$app->Tpl->Add('JQUERYREADY', "$('#archiv').click( function() { fnFilterColumn1( 0 ); } );");
for ($r = 1;$r <= 1;$r++) {
$app->Tpl->Add('JAVASCRIPT', '
function fnFilterColumn' . $r . ' ( i )
{
if(oMoreData' . $r . $name . '==1)
oMoreData' . $r . $name . ' = 0;
else
oMoreData' . $r . $name . ' = 1;
$(\'#' . $name . '\').dataTable().fnFilter(
\'\',
i,
0,0
);
}
');
}
$more_data1 = $app->Secure->GetGET("more_data1");
if ($more_data1 == 1) {
$where .= " OR k.aktiv <> 1";
} else {
}
$count = "SELECT count(DISTINCT id) FROM konten k WHERE $where";
// $groupby = "";
break;
}
$erg = false;
foreach ($erlaubtevars as $k => $v) {
if (isset($$v)) {
$erg[$v] = $$v;
}
}
return $erg;
}
function konten_list() {
$this->app->erp->MenuEintrag("index.php?module=konten&action=list", "&Uuml;bersicht");
$this->app->erp->MenuEintrag("index.php?module=konten&action=create", "Neu anlegen");
$this->app->erp->MenuEintrag("index.php", "Zur&uuml;ck");
$this->app->YUI->TableSearch('TAB1', 'konten_list', "show", "", "", basename(__FILE__), __CLASS__);
$this->app->Tpl->Parse('PAGE', "konten_list.tpl");
}
public function konten_delete() {
$id = (int) $this->app->Secure->GetGET('id');
$this->app->DB->Delete("UPDATE `konten` SET `aktiv` = 0 WHERE `id` = '{$id}'");
$this->app->Tpl->Set('MESSAGE', "<div class=\"info\">Der Eintrag wurde deaktiviert.</div>");
$this->konten_list();
}
/*
* Edit konten item
* If id is empty, create a new one
*/
function konten_edit() {
$id = $this->app->Secure->GetGET('id');
// Check if other users are editing this id
if($this->app->erp->DisableModul('artikel',$id))
{
return;
}
$this->app->Tpl->Set('ID', $id);
$this->app->erp->MenuEintrag("index.php?module=konten&action=edit&id=$id", "Details");
$this->app->erp->MenuEintrag("index.php?module=konten&action=list", "Zur&uuml;ck zur &Uuml;bersicht");
$id = $this->app->Secure->GetGET('id');
$input = $this->GetInput();
$submit = $this->app->Secure->GetPOST('submit');
if (empty($id)) {
// New item
$id = 'NULL';
}
if ($submit != '')
{
// Write to database
// Add checks here
$input['projekt'] = $this->app->erp->ReplaceProjekt(true,$input['projekt'],true);
$columns = "id, ";
$values = "$id, ";
$update = "";
$fix = "";
foreach ($input as $key => $value) {
$columns = $columns.$fix.$key;
$values = $values.$fix."'".$value."'";
$update = $update.$fix.$key." = '$value'";
$fix = ", ";
}
// echo($columns."<br>");
// echo($values."<br>");
// echo($update."<br>");
$sql = "INSERT INTO konten (".$columns.") VALUES (".$values.") ON DUPLICATE KEY UPDATE ".$update;
// echo($sql);
$this->app->DB->Update($sql);
if ($id == 'NULL') {
$msg = $this->app->erp->base64_url_encode("<div class=\"success\">Das Element wurde erfolgreich angelegt.</div>");
header("Location: index.php?module=konten&action=list&msg=$msg");
} else {
$this->app->Tpl->Set('MESSAGE', "<div class=\"success\">Die Einstellungen wurden erfolgreich &uuml;bernommen.</div>");
}
}
// Load values again from database
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',k.id,'\" />') AS `auswahl`";
$result = $this->app->DB->SelectArr("SELECT SQL_CALC_FOUND_ROWS k.id, $dropnbox, k.bezeichnung, k.kurzbezeichnung, k.type, k.erstezeile, k.datevkonto, k.blz, k.konto, k.swift, k.iban, k.lastschrift, k.hbci, k.hbcikennung, k.inhaber, k.aktiv, k.keineemail, k.firma, k.schreibbar, k.importletztenzeilenignorieren, k.liveimport, k.liveimport_passwort, k.liveimport_online, k.importtrennzeichen, k.codierung, k.importerstezeilenummer, k.importdatenmaskierung, k.importnullbytes, k.glaeubiger, k.geloescht, k.projekt, k.saldo_summieren, k.saldo_betrag, k.saldo_datum, k.importfelddatum, k.importfelddatumformat, k.importfelddatumformatausgabe, k.importfeldbetrag, k.importfeldbetragformat, k.importfeldbuchungstext, k.importfeldbuchungstextformat, k.importfeldwaehrung, k.importfeldwaehrungformat, k.importfeldhabensollkennung, k.importfeldkennunghaben, k.importfeldkennungsoll, k.importextrahabensoll, k.importfeldhaben, k.importfeldsoll, k.cronjobaktiv, k.cronjobverbuchen, k.last_import, k.importperiode_in_hours, k.id FROM konten k"." WHERE id=$id");
foreach ($result[0] as $key => $value) {
$this->app->Tpl->Set(strtoupper($key), $value);
}
/*
* Add displayed items later
*
$this->app->Tpl->Add('KURZUEBERSCHRIFT2', $email);
$this->app->Tpl->Add('EMAIL', $email);
$this->app->Tpl->Add('ANGEZEIGTERNAME', $angezeigtername);
*/
$this->app->YUI->AutoComplete('projekt','projektname',1);
$this->app->Tpl->Set('PROJEKT',$this->app->erp->ReplaceProjekt(false,$result[0]['projekt'],false));
$this->app->Tpl->Set('AKTIV',$result[0]['aktiv']==1?'checked':'');
$this->app->Tpl->Set('KEINEEMAIL',$result[0]['keineemail']==1?'checked':'');
$this->app->Tpl->Set('SCHREIBBAR',$result[0]['schreibbar']==1?'checked':'');
$this->app->Tpl->Set('LASTSCHRIFT',$result[0]['lastschrift']==1?'checked':'');
$this->app->Tpl->Set('SALDO_SUMMIEREN',$result[0]['saldo_summieren']==1?'checked':'');
$this->app->Tpl->Parse('PAGE', "konten_edit.tpl");
}
/**
* Get all paramters from html form and save into $input
*/
public function GetInput(): array {
$input = array();
//$input['EMAIL'] = $this->app->Secure->GetPOST('email');
$input['bezeichnung'] = $this->app->Secure->GetPOST('bezeichnung');
$input['kurzbezeichnung'] = $this->app->Secure->GetPOST('kurzbezeichnung');
$input['type'] = $this->app->Secure->GetPOST('type');
$input['erstezeile'] = $this->app->Secure->GetPOST('erstezeile');
$input['datevkonto'] = $this->app->Secure->GetPOST('datevkonto');
$input['blz'] = $this->app->Secure->GetPOST('blz');
$input['konto'] = $this->app->Secure->GetPOST('konto');
$input['swift'] = $this->app->Secure->GetPOST('swift');
$input['iban'] = $this->app->Secure->GetPOST('iban');
$input['lastschrift'] = $this->app->Secure->GetPOST('lastschrift');
$input['hbci'] = $this->app->Secure->GetPOST('hbci');
$input['hbcikennung'] = $this->app->Secure->GetPOST('hbcikennung');
$input['inhaber'] = $this->app->Secure->GetPOST('inhaber');
$input['aktiv'] = $this->app->Secure->GetPOST('aktiv');
$input['keineemail'] = $this->app->Secure->GetPOST('keineemail');
$input['firma'] = $this->app->Secure->GetPOST('firma');
$input['schreibbar'] = $this->app->Secure->GetPOST('schreibbar');
$input['importletztenzeilenignorieren'] = $this->app->Secure->GetPOST('importletztenzeilenignorieren');
$input['liveimport'] = $this->app->Secure->GetPOST('liveimport');
$input['liveimport_passwort'] = $this->app->Secure->GetPOST('liveimport_passwort');
$input['liveimport_online'] = $this->app->Secure->GetPOST('liveimport_online');
$input['importtrennzeichen'] = $this->app->Secure->GetPOST('importtrennzeichen');
$input['codierung'] = $this->app->Secure->GetPOST('codierung');
$input['importerstezeilenummer'] = $this->app->Secure->GetPOST('importerstezeilenummer');
$input['importdatenmaskierung'] = $this->app->Secure->GetPOST('importdatenmaskierung');
$input['importnullbytes'] = $this->app->Secure->GetPOST('importnullbytes');
$input['glaeubiger'] = $this->app->Secure->GetPOST('glaeubiger');
$input['geloescht'] = $this->app->Secure->GetPOST('geloescht');
$input['projekt'] = $this->app->Secure->GetPOST('projekt');
$input['saldo_summieren'] = $this->app->Secure->GetPOST('saldo_summieren');
$input['saldo_betrag'] = $this->app->Secure->GetPOST('saldo_betrag');
$input['saldo_datum'] = $this->app->Secure->GetPOST('saldo_datum');
$input['importfelddatum'] = $this->app->Secure->GetPOST('importfelddatum');
$input['importfelddatumformat'] = $this->app->Secure->GetPOST('importfelddatumformat');
$input['importfelddatumformatausgabe'] = $this->app->Secure->GetPOST('importfelddatumformatausgabe');
$input['importfeldbetrag'] = $this->app->Secure->GetPOST('importfeldbetrag');
$input['importfeldbetragformat'] = $this->app->Secure->GetPOST('importfeldbetragformat');
$input['importfeldbuchungstext'] = $this->app->Secure->GetPOST('importfeldbuchungstext');
$input['importfeldbuchungstextformat'] = $this->app->Secure->GetPOST('importfeldbuchungstextformat');
$input['importfeldwaehrung'] = $this->app->Secure->GetPOST('importfeldwaehrung');
$input['importfeldwaehrungformat'] = $this->app->Secure->GetPOST('importfeldwaehrungformat');
$input['importfeldhabensollkennung'] = $this->app->Secure->GetPOST('importfeldhabensollkennung');
$input['importfeldkennunghaben'] = $this->app->Secure->GetPOST('importfeldkennunghaben');
$input['importfeldkennungsoll'] = $this->app->Secure->GetPOST('importfeldkennungsoll');
$input['importextrahabensoll'] = $this->app->Secure->GetPOST('importextrahabensoll');
$input['importfeldhaben'] = $this->app->Secure->GetPOST('importfeldhaben');
$input['importfeldsoll'] = $this->app->Secure->GetPOST('importfeldsoll');
$input['cronjobaktiv'] = $this->app->Secure->GetPOST('cronjobaktiv');
$input['cronjobverbuchen'] = $this->app->Secure->GetPOST('cronjobverbuchen');
$input['last_import'] = $this->app->Secure->GetPOST('last_import');
$input['importperiode_in_hours'] = $this->app->Secure->GetPOST('importperiode_in_hours');
return $input;
}
/*
* Set all fields in the page corresponding to $input
*/
function SetInput($input) {
// $this->app->Tpl->Set('EMAIL', $input['email']);
$this->app->Tpl->Set('BEZEICHNUNG', $input['bezeichnung']);
$this->app->Tpl->Set('KURZBEZEICHNUNG', $input['kurzbezeichnung']);
$this->app->Tpl->Set('TYPE', $input['type']);
$this->app->Tpl->Set('ERSTEZEILE', $input['erstezeile']);
$this->app->Tpl->Set('DATEVKONTO', $input['datevkonto']);
$this->app->Tpl->Set('BLZ', $input['blz']);
$this->app->Tpl->Set('KONTO', $input['konto']);
$this->app->Tpl->Set('SWIFT', $input['swift']);
$this->app->Tpl->Set('IBAN', $input['iban']);
$this->app->Tpl->Set('LASTSCHRIFT', $input['lastschrift']);
$this->app->Tpl->Set('HBCI', $input['hbci']);
$this->app->Tpl->Set('HBCIKENNUNG', $input['hbcikennung']);
$this->app->Tpl->Set('INHABER', $input['inhaber']);
$this->app->Tpl->Set('AKTIV', $input['aktiv']);
$this->app->Tpl->Set('KEINEEMAIL', $input['keineemail']);
$this->app->Tpl->Set('FIRMA', $input['firma']);
$this->app->Tpl->Set('SCHREIBBAR', $input['schreibbar']);
$this->app->Tpl->Set('IMPORTLETZTENZEILENIGNORIEREN', $input['importletztenzeilenignorieren']);
$this->app->Tpl->Set('LIVEIMPORT', $input['liveimport']);
$this->app->Tpl->Set('LIVEIMPORT_PASSWORT', $input['liveimport_passwort']);
$this->app->Tpl->Set('LIVEIMPORT_ONLINE', $input['liveimport_online']);
$this->app->Tpl->Set('IMPORTTRENNZEICHEN', $input['importtrennzeichen']);
$this->app->Tpl->Set('CODIERUNG', $input['codierung']);
$this->app->Tpl->Set('IMPORTERSTEZEILENUMMER', $input['importerstezeilenummer']);
$this->app->Tpl->Set('IMPORTDATENMASKIERUNG', $input['importdatenmaskierung']);
$this->app->Tpl->Set('IMPORTNULLBYTES', $input['importnullbytes']);
$this->app->Tpl->Set('GLAEUBIGER', $input['glaeubiger']);
$this->app->Tpl->Set('GELOESCHT', $input['geloescht']);
$this->app->Tpl->Set('PROJEKT', $input['projekt']);
$this->app->Tpl->Set('SALDO_SUMMIEREN', $input['saldo_summieren']);
$this->app->Tpl->Set('SALDO_BETRAG', $input['saldo_betrag']);
$this->app->Tpl->Set('SALDO_DATUM', $input['saldo_datum']);
$this->app->Tpl->Set('IMPORTFELDDATUM', $input['importfelddatum']);
$this->app->Tpl->Set('IMPORTFELDDATUMFORMAT', $input['importfelddatumformat']);
$this->app->Tpl->Set('IMPORTFELDDATUMFORMATAUSGABE', $input['importfelddatumformatausgabe']);
$this->app->Tpl->Set('IMPORTFELDBETRAG', $input['importfeldbetrag']);
$this->app->Tpl->Set('IMPORTFELDBETRAGFORMAT', $input['importfeldbetragformat']);
$this->app->Tpl->Set('IMPORTFELDBUCHUNGSTEXT', $input['importfeldbuchungstext']);
$this->app->Tpl->Set('IMPORTFELDBUCHUNGSTEXTFORMAT', $input['importfeldbuchungstextformat']);
$this->app->Tpl->Set('IMPORTFELDWAEHRUNG', $input['importfeldwaehrung']);
$this->app->Tpl->Set('IMPORTFELDWAEHRUNGFORMAT', $input['importfeldwaehrungformat']);
$this->app->Tpl->Set('IMPORTFELDHABENSOLLKENNUNG', $input['importfeldhabensollkennung']);
$this->app->Tpl->Set('IMPORTFELDKENNUNGHABEN', $input['importfeldkennunghaben']);
$this->app->Tpl->Set('IMPORTFELDKENNUNGSOLL', $input['importfeldkennungsoll']);
$this->app->Tpl->Set('IMPORTEXTRAHABENSOLL', $input['importextrahabensoll']);
$this->app->Tpl->Set('IMPORTFELDHABEN', $input['importfeldhaben']);
$this->app->Tpl->Set('IMPORTFELDSOLL', $input['importfeldsoll']);
$this->app->Tpl->Set('CRONJOBAKTIV', $input['cronjobaktiv']);
$this->app->Tpl->Set('CRONJOBVERBUCHEN', $input['cronjobverbuchen']);
$this->app->Tpl->Set('LAST_IMPORT', $input['last_import']);
$this->app->Tpl->Set('IMPORTPERIODE_IN_HOURS', $input['importperiode_in_hours']);
}
}
+539
View File
@@ -0,0 +1,539 @@
<?php
/*
* Copyright (c) 2022 OpenXE project
*/
use Xentral\Components\Database\Exception\QueryFailureException;
class Kontoauszuege {
function __construct($app, $intern = false) {
$this->app = $app;
if ($intern)
return;
$this->app->ActionHandlerInit($this);
$this->app->ActionHandler("list", "kontoauszuege_konto_list");
$this->app->ActionHandler("listentries", "kontoauszuege_list");
// $this->app->ActionHandler("create", "kontoauszuege_edit"); // This automatically adds a "New" button
$this->app->ActionHandler("edit", "kontoauszuege_edit");
$this->app->ActionHandler("delete", "kontoauszuege_delete");
$this->app->DefaultActionHandler("list");
$this->app->ActionHandlerListen($app);
}
public function Install() {
/* Fill out manually later */
}
function TableSearch(&$app, $name, $erlaubtevars) {
switch ($name) {
case "kontoauszuege_konto_list":
$allowed['konten_list'] = array('list');
$heading = array('Bezeichnung', 'Kurzbezeichnung', 'Typ', 'Kontostand','Letzter Import', 'Men&uuml;');
// $width = array('1%','1%','10%'); // Fill out manually later
// columns that are aligned right (numbers etc)
// $alignright = array(4,5,6,7,8); sdds
$findcols = array('k.bezeichnung', 'k.kurzbezeichnung', 'k.type', 'k.kontostand','ka.datum', 'k.id');
$searchsql = array('k.bezeichnung', 'k.kurzbezeichnung', 'k.datevkonto', 'k.blz', 'k.konto', 'k.swift', 'k.iban', 'k.inhaber', 'k.firma','p.abkuerzung');
$defaultorder = 1;
$defaultorderdesc = 0;
// $sumcol = array(5);
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',k.id,'\" />') AS `auswahl`";
$menu = "<table cellpadding=0 cellspacing=0><tr><td nowrap>" . "<a href=\"index.php?module=kontoauszuege&action=listentries&kid=%value%\"><img src=\"./themes/{$app->Conf->WFconf['defaulttheme']}/images/edit.svg\" border=\"0\"></a></td></tr></table>";
$saldolink = array (
'<a href=\"index.php?module=fibu_buchungen&action=zuordnen&typ=kontoauszuege',
'">',
['sql' => $this->app->erp->FormatMenge('SUM(COALESCE(fb.betrag,0))',2)],
'</a>'
);
$sql = "SELECT
k.id,
k.bezeichnung,
k.kurzbezeichnung,
".$this->app->erp->FormatUCfirst('k.type').",
".$this->app->erp->FormatMenge('SUM(COALESCE(ka.soll,0))+k.saldo_betrag',2)." AS kontostand,
".$this->app->erp->FormatDatetime("MIN(ka.importdatum)")." AS datum,
k.id
FROM
konten k
LEFT JOIN kontoauszuege ka ON
k.id = ka.konto";
$where = " k.aktiv = 1 AND ka.importfehler IS NULL ";
// Toggle filters
$app->Tpl->Add('JQUERYREADY', "$('#archiv').click( function() { fnFilterColumn1( 0 ); } );");
for ($r = 1;$r <= 1;$r++) {
$app->Tpl->Add('JAVASCRIPT', '
function fnFilterColumn' . $r . ' ( i )
{
if(oMoreData' . $r . $name . '==1)
oMoreData' . $r . $name . ' = 0;
else
oMoreData' . $r . $name . ' = 1;
$(\'#' . $name . '\').dataTable().fnFilter(
\'\',
i,
0,0
);
}
');
}
$more_data1 = $app->Secure->GetGET("more_data1");
if ($more_data1 == 1) {
$where .= " OR k.aktiv <> 1";
} else {
}
// echo($sql);
// $count = "SELECT count(DISTINCT id) FROM konten k WHERE $where";
$groupby = " GROUP BY k.id";
break;
case "kontoauszuege_list":
$allowed['kontoauszuege_list'] = array('list');
$kontoid = $this->app->User->getParameter('kontoauszuege_konto_id');
$onlysaldo = $this->app->User->getParameter('kontoauszuege_only_saldo');
$heading = array('','', 'Importdatum', 'Konto', 'Datum', 'Betrag', 'Waehrung', 'Buchungstext','Interne Bemerkung', 'Saldo', 'Men&uuml;');
$width = array('1%','1%', '1%', '10%', '1%', '1%', '1%', '20%', '20%', '1%', '1%'); // Fill out manually later
// columns that are aligned right (numbers etc)
$alignright = array(6);
$sumcol = array(10);
$findcols = array('q.id','q.id','q.kurzbezeichnung', 'q.importdatum', 'q.buchung', 'q.soll', 'q.waehrung', 'q.buchungstext','q.internebemerkung','q.saldo');
$searchsql = array('q.kurzbezeichnung', 'q.buchung', 'q.soll', 'q.buchungstext','q.internebemerkung');
$defaultorder = 1;
$defaultorderdesc = 0;
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',k.id,'\" />') AS `auswahl`";
$menu = "<table cellpadding=0 cellspacing=0><tr><td nowrap>" . "<a href=\"index.php?module=kontoauszuege&action=edit&id=%value%\"><img src=\"./themes/{$app->Conf->WFconf['defaulttheme']}/images/edit.svg\" border=\"0\"></a>&nbsp;<a href=\"#\" onclick=DeleteDialog(\"index.php?module=kontoauszuege&action=delete&kid=".$kontoid."&onlysaldo=".$onlysaldo."&id=%value%\");>" . "<img src=\"themes/{$app->Conf->WFconf['defaulttheme']}/images/delete.svg\" border=\"0\"></a>" . "</td></tr></table>";
// Toggle filters
$app->Tpl->Add('JQUERYREADY', "$('#importfehler').click( function() { fnFilterColumn1( 0 ); } );");
for ($r = 1;$r <= 4;$r++) {
$app->Tpl->Add('JAVASCRIPT', '
function fnFilterColumn' . $r . ' ( i )
{
if(oMoreData' . $r . $name . '==1)
oMoreData' . $r . $name . ' = 0;
else
oMoreData' . $r . $name . ' = 1;
$(\'#' . $name . '\').dataTable().fnFilter(
\'\',
i,
0,0
);
}
');
}
$more_data1 = $app->Secure->GetGET("more_data1");
if ($more_data1 == 1) {
$subwhere .= "";
} else {
$subwhere .= " AND k.importfehler IS NULL ";
}
// END Toggle filters
$sql = "SELECT SQL_CALC_FOUND_ROWS * FROM ( SELECT
k.id,
$dropnbox,
".$app->erp->FormatDateTimeShort('k.importdatum')." AS importdatum,
(SELECT kurzbezeichnung FROM konten WHERE konten.id = k.konto) as kurzbezeichnung,
".$app->erp->FormatDate('k.buchung')." as buchung,
IF(
k.importfehler,
CONCAT(
'<del>',
".$app->erp->FormatMenge('(k.soll)',2).",
'</del>'
),
".$app->erp->FormatMenge('(k.soll)',2)."),
k.waehrung,
k.buchungstext,
k.internebemerkung,
".$app->erp->FormatMenge('SUM(fb.betrag)',2)." AS saldo,
k.id as menuid,
SUM(fb.betrag) AS saldonum
FROM kontoauszuege k
LEFT JOIN fibu_buchungen_alle fb ON
fb.id = k.id AND fb.typ = 'kontoauszuege'
WHERE k.konto = ".$kontoid.$subwhere."
GROUP BY k.id ) AS q
";
$where = "1";
if ($onlysaldo) {
$where .= " AND saldonum != 0";
}
// $count = "SELECT count(DISTINCT id) FROM kontoauszuege k WHERE $where";
// $groupby = "";
// echo($sql." WHERE ".$where." ".$groupby);
break;
case "kontoauszuege_salden":
$allowed['kontoauszuege_list'] = array('list');
$kontoid = $this->app->User->getParameter('kontoauszuege_konto_id');
$onlysaldo = $this->app->User->getParameter('kontoauszuege_only_saldo');
$heading = array('','', 'Buchungstext', 'Betrag', 'Waehrung', 'Betrag zuordnen', 'Beleg', 'ID','Beleg-Nr.','', 'Men&uuml;');
$width = array('1%','1%', '20%', '1%', '1%', '1%', '1%', '1%','1%', '1%','1%');
// columns that are aligned right (numbers etc)
$alignright = array(6);
$sumcol = array(10);
$findcols = array('q.id','q.id','q.konto', 'q.importdatum', 'q.buchung', 'q.soll', 'q.waehrung', 'q.buchungstext','q.internebemerkung','q.saldo');
$searchsql = array('q.konto', 'q.buchung', 'q.soll', 'q.buchungstext','q.internebemerkung');
$defaultorder = 1;
$defaultorderdesc = 0;
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',q.id,'\"',if(b.doc_belegnr IS NOT NULL,'checked',''),' />') AS `auswahl`";
$menu = "<table cellpadding=0 cellspacing=0><tr><td nowrap>" . "<a href=\"index.php?module=kontoauszuege&action=edit&id=%value%\"><img src=\"./themes/{$app->Conf->WFconf['defaulttheme']}/images/edit.svg\" border=\"0\"></a>&nbsp;<a href=\"#\" onclick=DeleteDialog(\"index.php?module=kontoauszuege&action=delete&kid=".$kontoid."&onlysaldo=".$onlysaldo."&id=%value%\");>" . "<img src=\"themes/{$app->Conf->WFconf['defaulttheme']}/images/delete.svg\" border=\"0\"></a>" . "</td></tr></table>";
$sql = "SELECT
".$this->app->erp->FormatUCfirst('typ')."
SUM(betrag)
FROM `fibu_buchungen_alle`
";
$where = "1";
if ($onlysaldo) {
$where .= " AND q.saldonum != 0";
}
// $count = "SELECT count(DISTINCT id) FROM kontoauszuege k WHERE $where";
$groupby = "GROUP BY typ";
// echo($sql." WHERE ".$where." ".$groupby);
break;
}
$erg = false;
foreach ($erlaubtevars as $k => $v) {
if (isset($$v)) {
$erg[$v] = $$v;
}
}
return $erg;
}
function kontoauszuege_konto_list() {
$this->app->erp->MenuEintrag("index.php?module=kontoauszuege&action=list", "&Uuml;bersicht");
// $this->app->erp->MenuEintrag("index.php?module=kontoauszuege&action=create", "Neu anlegen");
$this->app->erp->MenuEintrag("index.php", "Zur&uuml;ck");
$this->app->YUI->TableSearch('TAB1', 'kontoauszuege_konto_list', "show", "", "", basename(__FILE__), __CLASS__);
$this->app->Tpl->Parse('PAGE', "kontoauszuege_konto_list.tpl");
}
function kontoauszuege_mark_as_error(int $id) : ?string {
$sql = "SELECT id FROM fibu_buchungen_alle WHERE CONCAT(doc_typ,doc_id) <> CONCAT('kontoauszuege','".$id."') AND typ = 'kontoauszuege' AND id = ".$id;
$result = $this->app->DB->SelectArr($sql);
if (!empty($result)) {
return("Es existieren Buchungen, Eintrag wurde nicht als Importfehler markiert!");
} else {
$this->app->DB->Delete("UPDATE `kontoauszuege` SET importfehler = 1 WHERE `id` = '{$id}'");
return("Der Eintrag wurde als Importfehler markiert.");
}
return(null);
}
function kontoauszuege_list() {
// Process multi action
$auswahl = $this->app->Secure->GetPOST('auswahl');
$selectedIds = [];
if(!empty($auswahl)) {
foreach($auswahl as $selectedId) {
$selectedId = (int)$selectedId;
if($selectedId > 0) {
$selectedIds[] = $selectedId;
}
}
$submit = $this->app->Secure->GetPOST('ausfuehren');
if ($submit == 'Importfehler') {
$message = "";
foreach ($selectedIds as $selectedId) {
$result = $this->kontoauszuege_mark_as_error($selectedId);
if ($result) {
$message = $result;
}
}
if ($message) {
$this->app->Tpl->Set('MESSAGE', "<div class=\"error\">".$message."</div>");
} else {
$this->app->Tpl->Set('MESSAGE', "<div class=\"warning\">Eintr&auml;ge wurden als Importfehler markiert.</div>");
}
}
}
$this->app->erp->MenuEintrag("index.php?module=kontoauszuege&action=list", "&Uuml;bersicht");
// $this->app->erp->MenuEintrag("index.php?module=kontoauszuege&action=create", "Neu anlegen");
$this->app->erp->MenuEintrag("index.php", "Zur&uuml;ck");
$kontoid = $this->app->Secure->GetGET('kid');
$this->app->User->SetParameter('kontoauszuege_konto_id', $kontoid);
$onlysaldo = $this->app->Secure->GetGET('onlysaldo');
$this->app->User->SetParameter('kontoauszuege_only_saldo', $onlysaldo);
if ($onlysaldo) {
$this->app->Tpl->Set('INFO','Nicht zugeordnete Posten');
}
$this->app->YUI->TableSearch('TAB1', 'kontoauszuege_list', "show", "", "", basename(__FILE__), __CLASS__);
$this->app->Tpl->Parse('PAGE', "kontoauszuege_list.tpl");
}
public function kontoauszuege_delete() {
$id = (int) $this->app->Secure->GetGET('id');
$result = $this->kontoauszuege_mark_as_error($id);
if ($result) {
$this->app->Tpl->Set('MESSAGE', "<div class=\"error\">".$result."</div>");
} else {
$this->app->Tpl->Set('MESSAGE', "<div class=\"warning\">Der Eintrag wurde als Importfehler markiert.</div>");
}
$this->kontoauszuege_list();
}
/*
* Edit kontoauszuege item
* If id is empty, create a new one
*/
function kontoauszuege_edit() {
$id = $this->app->Secure->GetGET('id');
// Check if other users are editing this id
if($this->app->erp->DisableModul('artikel',$id))
{
return;
}
$this->app->Tpl->Set('ID', $id);
$this->app->erp->MenuEintrag("index.php?module=kontoauszuege&action=edit&id=$id", "Details");
$this->app->erp->MenuEintrag("index.php?module=kontoauszuege&action=list", "Zur&uuml;ck zur &Uuml;bersicht");
$id = $this->app->Secure->GetGET('id');
$input = $this->GetInput();
$submit = $this->app->Secure->GetPOST('submit');
/* if (empty($id)) {
// New item
$id = 'NULL';
} */
if ($submit != '')
{
// Write to database
// Add checks here
$columns = "id, ";
$values = "$id, ";
$update = "";
$fix = "";
foreach ($input as $key => $value) {
$columns = $columns.$fix.$key;
$values = $values.$fix."'".$value."'";
$update = $update.$fix.$key." = '$value'";
$fix = ", ";
}
// echo($columns."<br>");
// echo($values."<br>");
// echo($update."<br>");
$sql = "INSERT INTO kontoauszuege (".$columns.") VALUES (".$values.") ON DUPLICATE KEY UPDATE ".$update;
// echo($sql);
$this->app->DB->Update($sql);
if ($id == 'NULL') {
$msg = $this->app->erp->base64_url_encode("<div class=\"success\">Das Element wurde erfolgreich angelegt.</div>");
header("Location: index.php?module=kontoauszuege&action=list&msg=$msg");
} else {
$this->app->Tpl->Set('MESSAGE', "<div class=\"success\">Die Einstellungen wurden erfolgreich &uuml;bernommen.</div>");
}
}
// Load values again from database
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`, CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',k.id,'\" />') AS `auswahl`";
$result = $this->app->DB->SelectArr("SELECT SQL_CALC_FOUND_ROWS k.id, $dropnbox, k.konto, k.buchung, k.originalbuchung, k.vorgang, k.originalvorgang, k.soll, k.originalsoll, k.haben, k.originalhaben, k.gebuehr, k.originalgebuehr, k.waehrung, k.originalwaehrung, k.fertig, k.datev_abgeschlossen, k.buchungstext, k.gegenkonto, k.belegfeld1, k.bearbeiter, k.mailbenachrichtigung, k.pruefsumme, k.kostenstelle, k.importgroup, k.diff, k.diffangelegt, k.internebemerkung, k.importfehler, k.parent, k.sort, k.doctype, k.doctypeid, k.vorauswahltyp, k.vorauswahlparameter, k.klaerfall, k.klaergrund, k.bezugtyp, k.bezugparameter, k.vorauswahlvorschlag, k.id FROM kontoauszuege k"." WHERE id=$id");
foreach ($result[0] as $key => $value) {
$this->app->Tpl->Set(strtoupper($key), $value);
}
/*
* Add displayed items later
*
$this->app->Tpl->Add('KURZUEBERSCHRIFT2', $email);
$this->app->Tpl->Add('EMAIL', $email);
$this->app->Tpl->Add('ANGEZEIGTERNAME', $angezeigtername);
*/
$sql = "SELECT kurzbezeichnung FROM konten WHERE id=".$result[0]['konto'];
$konto = $this->app->DB->Select($sql);
$this->app->Tpl->Set('KONTO', $konto);
$this->app->Tpl->Set('BUCHUNG', $this->app->erp->ReplaceDatum(false,$result[0]['buchung'],false));
$this->app->Tpl->Set('SOLL', $this->app->erp->ReplaceBetrag(false,$result[0]['soll'],false));
$this->app->Tpl->Parse('PAGE', "kontoauszuege_edit.tpl");
}
/**
* Get all paramters from html form and save into $input
*/
public function GetInput(): array {
$input = array();
//$input['EMAIL'] = $this->app->Secure->GetPOST('email');
/* $input['konto'] = $this->app->Secure->GetPOST('konto');
$input['buchung'] = $this->app->Secure->GetPOST('buchung');
$input['originalbuchung'] = $this->app->Secure->GetPOST('originalbuchung');
$input['vorgang'] = $this->app->Secure->GetPOST('vorgang');
$input['originalvorgang'] = $this->app->Secure->GetPOST('originalvorgang');
$input['soll'] = $this->app->Secure->GetPOST('soll');
$input['originalsoll'] = $this->app->Secure->GetPOST('originalsoll');
$input['haben'] = $this->app->Secure->GetPOST('haben');
$input['originalhaben'] = $this->app->Secure->GetPOST('originalhaben');
$input['gebuehr'] = $this->app->Secure->GetPOST('gebuehr');
$input['originalgebuehr'] = $this->app->Secure->GetPOST('originalgebuehr');
$input['waehrung'] = $this->app->Secure->GetPOST('waehrung');
$input['originalwaehrung'] = $this->app->Secure->GetPOST('originalwaehrung');
$input['fertig'] = $this->app->Secure->GetPOST('fertig');
$input['datev_abgeschlossen'] = $this->app->Secure->GetPOST('datev_abgeschlossen');
$input['buchungstext'] = $this->app->Secure->GetPOST('buchungstext');
$input['gegenkonto'] = $this->app->Secure->GetPOST('gegenkonto');
$input['belegfeld1'] = $this->app->Secure->GetPOST('belegfeld1');
$input['bearbeiter'] = $this->app->Secure->GetPOST('bearbeiter');
$input['mailbenachrichtigung'] = $this->app->Secure->GetPOST('mailbenachrichtigung');
$input['pruefsumme'] = $this->app->Secure->GetPOST('pruefsumme');
$input['kostenstelle'] = $this->app->Secure->GetPOST('kostenstelle');
$input['importgroup'] = $this->app->Secure->GetPOST('importgroup');
$input['diff'] = $this->app->Secure->GetPOST('diff');
$input['diffangelegt'] = $this->app->Secure->GetPOST('diffangelegt');
*/ $input['internebemerkung'] = $this->app->Secure->GetPOST('internebemerkung');
/* $input['importfehler'] = $this->app->Secure->GetPOST('importfehler');
$input['parent'] = $this->app->Secure->GetPOST('parent');
$input['sort'] = $this->app->Secure->GetPOST('sort');
$input['doctype'] = $this->app->Secure->GetPOST('doctype');
$input['doctypeid'] = $this->app->Secure->GetPOST('doctypeid');
$input['vorauswahltyp'] = $this->app->Secure->GetPOST('vorauswahltyp');
$input['vorauswahlparameter'] = $this->app->Secure->GetPOST('vorauswahlparameter');
$input['klaerfall'] = $this->app->Secure->GetPOST('klaerfall');
$input['klaergrund'] = $this->app->Secure->GetPOST('klaergrund');
$input['bezugtyp'] = $this->app->Secure->GetPOST('bezugtyp');
$input['bezugparameter'] = $this->app->Secure->GetPOST('bezugparameter');
$input['vorauswahlvorschlag'] = $this->app->Secure->GetPOST('vorauswahlvorschlag');*/
return $input;
}
/*
* Set all fields in the page corresponding to $input
*/
function SetInput($input) {
// $this->app->Tpl->Set('EMAIL', $input['email']);
$this->app->Tpl->Set('KONTO', $input['konto']);
$this->app->Tpl->Set('BUCHUNG', $input['buchung']);
$this->app->Tpl->Set('ORIGINALBUCHUNG', $input['originalbuchung']);
$this->app->Tpl->Set('VORGANG', $input['vorgang']);
$this->app->Tpl->Set('ORIGINALVORGANG', $input['originalvorgang']);
$this->app->Tpl->Set('SOLL', $input['soll']);
$this->app->Tpl->Set('ORIGINALSOLL', $input['originalsoll']);
$this->app->Tpl->Set('HABEN', $input['haben']);
$this->app->Tpl->Set('ORIGINALHABEN', $input['originalhaben']);
$this->app->Tpl->Set('GEBUEHR', $input['gebuehr']);
$this->app->Tpl->Set('ORIGINALGEBUEHR', $input['originalgebuehr']);
$this->app->Tpl->Set('WAEHRUNG', $input['waehrung']);
$this->app->Tpl->Set('ORIGINALWAEHRUNG', $input['originalwaehrung']);
$this->app->Tpl->Set('FERTIG', $input['fertig']);
$this->app->Tpl->Set('DATEV_ABGESCHLOSSEN', $input['datev_abgeschlossen']);
$this->app->Tpl->Set('BUCHUNGSTEXT', $input['buchungstext']);
$this->app->Tpl->Set('GEGENKONTO', $input['gegenkonto']);
$this->app->Tpl->Set('BELEGFELD1', $input['belegfeld1']);
$this->app->Tpl->Set('BEARBEITER', $input['bearbeiter']);
$this->app->Tpl->Set('MAILBENACHRICHTIGUNG', $input['mailbenachrichtigung']);
$this->app->Tpl->Set('PRUEFSUMME', $input['pruefsumme']);
$this->app->Tpl->Set('KOSTENSTELLE', $input['kostenstelle']);
$this->app->Tpl->Set('IMPORTGROUP', $input['importgroup']);
$this->app->Tpl->Set('DIFF', $input['diff']);
$this->app->Tpl->Set('DIFFANGELEGT', $input['diffangelegt']);
$this->app->Tpl->Set('INTERNEBEMERKUNG', $input['internebemerkung']);
$this->app->Tpl->Set('IMPORTFEHLER', $input['importfehler']);
$this->app->Tpl->Set('PARENT', $input['parent']);
$this->app->Tpl->Set('SORT', $input['sort']);
$this->app->Tpl->Set('DOCTYPE', $input['doctype']);
$this->app->Tpl->Set('DOCTYPEID', $input['doctypeid']);
$this->app->Tpl->Set('VORAUSWAHLTYP', $input['vorauswahltyp']);
$this->app->Tpl->Set('VORAUSWAHLPARAMETER', $input['vorauswahlparameter']);
$this->app->Tpl->Set('KLAERFALL', $input['klaerfall']);
$this->app->Tpl->Set('KLAERGRUND', $input['klaergrund']);
$this->app->Tpl->Set('BEZUGTYP', $input['bezugtyp']);
$this->app->Tpl->Set('BEZUGPARAMETER', $input['bezugparameter']);
$this->app->Tpl->Set('VORAUSWAHLVORSCHLAG', $input['vorauswahlvorschlag']);
}
}
+92 -39
View File
@@ -283,7 +283,7 @@ class Rechnung extends GenRechnung
$this->app->erp->RechnungProtokoll($invoiceId,'Rechnung manuell als bezahlt entfernt');
$this->app->DB->Update(
"UPDATE rechnung
SET zahlungsstatus='offen',bezahlt_am = NULL, ist='0',
SET zahlungsstatus='offen',bezahlt_am = NULL,
mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Manuell als bezahlt entfernt am ".date('d.m.Y')."')
WHERE id='$invoiceId'"
);
@@ -305,7 +305,7 @@ class Rechnung extends GenRechnung
$id = $this->app->Secure->GetGET('id');
$this->app->erp->RechnungProtokoll($id,'Rechnung Stornierung rückgängig gemacht');
$this->app->DB->Update("UPDATE rechnung SET status='freigegeben',zahlungsstatus='offen',schreibschutz=0,bezahlt_am = NULL, ist='0',mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Rechnung Stornierung rückgängig gemacht ".date('d.m.Y')."') WHERE id='$id'");
$this->app->DB->Update("UPDATE rechnung SET status='freigegeben',zahlungsstatus='offen',schreibschutz=0,bezahlt_am = NULL, mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Rechnung Stornierung rückgängig gemacht ".date('d.m.Y')."') WHERE id='$id'");
$this->app->Location->execute("index.php?module=rechnung&action=edit&id=$id");
}
@@ -324,7 +324,7 @@ class Rechnung extends GenRechnung
$this->app->DB->Update(
"UPDATE rechnung
SET zahlungsstatus='bezahlt',bezahlt_am = now(), ist=soll,mahnwesenfestsetzen='1',
SET zahlungsstatus='bezahlt',bezahlt_am = now(), mahnwesenfestsetzen='1',
mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Manuell als bezahlt markiert am ".date('d.m.Y')."')
WHERE id='$invoiceId'"
);
@@ -887,29 +887,8 @@ class Rechnung extends GenRechnung
$this->app->Tpl->Set('ANGEBOTFARBE',"grey");
$this->app->Tpl->Set('ANGEBOTTEXT',"Das Angebot wird bearbeitet und wurde noch nicht freigegeben und abgesendet!");
}
$this->app->Tpl->Set('ZAHLUNGEN',"<table width=100% border=0 class=auftrag_cell cellpadding=0 cellspacing=0>Erst ab Version Enterprise verf&uuml;gbar</table>");
if (!is_null($gutschrift)) {
if((!empty($gutschrift)?count($gutschrift):0) > 0)
$this->app->Tpl->Add('ZAHLUNGEN',"<div class=\"info\">Zu dieser Rechnung existiert eine Gutschrift!</div>");
else {
if($auftragArr[0]['zahlungsstatus']!="bezahlt")
$this->app->Tpl->Add('ZAHLUNGEN',"<div class=\"warning\">Diese Rechnung ist noch nicht komplett bezahlt!</div>");
else
{
if(!empty($auftragArr[0]['bezahlt_am']) && $auftragArr[0]['bezahlt_am'] != '0000-00-00')
{
$this->app->Tpl->Add('ZAHLUNGEN',"<div class=\"success\">Diese Rechnung wurde am ".$this->app->String->Convert($auftragArr[0]['bezahlt_am'],"%1-%2-%3","%3.%2.%1")." bezahlt.</div>");
}else{
$this->app->Tpl->Add('ZAHLUNGEN',"<div class=\"success\">Diese Rechnung ist bezahlt.</div>");
}
}
}
}
$this->app->Tpl->Set('ZAHLUNGEN',$this->RechnungZahlung(true));
$this->app->Tpl->Set('RECHNUNGADRESSE',$this->Rechnungsadresse($auftragArr[0]['id']));
@@ -1582,6 +1561,9 @@ class Rechnung extends GenRechnung
$this->app->erp->RechnungNeuberechnen($id);
}
// ALWAYS
$this->app->erp->RechnungNeuberechnen($id);
if($cmd === 'dadown')
{
$erg['status'] = 0;
@@ -1766,9 +1748,8 @@ class Rechnung extends GenRechnung
$this->app->Tpl->Set('VORKASSE','');
}
$saldo=$this->app->DB->Select("SELECT ist-skonto_gegeben FROM rechnung WHERE id='$id'");
$this->app->Tpl->Set('LIVEIST',"$saldo");
$ist = $this->app->erp->EUR($this->app->erp->GetSaldoDokument($id,'rechnung')['betrag']);
$this->app->Tpl->Set('ISTDB',$ist);
if($schreibschutz=="1" && $this->app->erp->RechteVorhanden('rechnung','schreibschutz'))
{
@@ -1788,10 +1769,13 @@ class Rechnung extends GenRechnung
$this->app->erp->RemoveReadonly('mahnwesenfestsetzen');
$this->app->erp->RemoveReadonly('mahnwesen');
$this->app->erp->RemoveReadonly('bezahlt_am');
/*
'ist' should not be edited manually
$this->app->erp->RemoveReadonly('ist');
if($this->app->erp->Firmendaten('mahnwesenmitkontoabgleich')!='1' || $this->app->DB->Select("SELECT mahnwesenfestsetzen FROM rechnung WHERE id='$id' LIMIT 1")==1)
$this->app->erp->RemoveReadonly('ist');
$this->app->erp->RemoveReadonly('ist');*/
//$auftrag= $this->app->DB->Select("SELECT auftrag FROM rechnung WHERE id='$id' LIMIT 1");
@@ -1812,8 +1796,10 @@ class Rechnung extends GenRechnung
}
$speichern = $this->app->Secure->GetPOST('speichern');
if($speichern!='' && $this->app->erp->RechteVorhanden('rechnung','mahnwesen'))
{
$mahnwesen_datum = $this->app->Secure->GetPOST('mahnwesen_datum');
$bezahlt_am = $this->app->Secure->GetPOST('bezahlt_am');
$mahnwesen_gesperrt = $this->app->Secure->GetPOST('mahnwesen_gesperrt');
@@ -1839,17 +1825,16 @@ class Rechnung extends GenRechnung
$alte_mahnstufe = $this->app->DB->Select("SELECT mahnwesen FROM rechnung WHERE id='$id' LIMIT 1");
if($alte_mahnstufe!=$mahnwesen) $versendet=0; else $versendet=1;
if($mahnwesenfestsetzen=='1')
{
/* if($mahnwesenfestsetzen=='1')
{*/
$this->app->DB->Update("UPDATE rechnung SET mahnwesen_internebemerkung='$mahnwesen_internebemerkung',zahlungsstatus='$zahlungsstatus',versendet_mahnwesen='$versendet',
mahnwesen_gesperrt='$mahnwesen_gesperrt',mahnwesen_datum='$mahnwesen_datum', mahnwesenfestsetzen='$mahnwesenfestsetzen',internebemerkung='$internebemerkung',
mahnwesen='$mahnwesen',ist='$ist',skonto_gegeben='$skonto_gegeben',bezahlt_am='$bezahlt_am' WHERE id='$id' LIMIT 1");
} else {
mahnwesen='$mahnwesen',skonto_gegeben='$skonto_gegeben',bezahlt_am='$bezahlt_am' WHERE id='$id' LIMIT 1");
/* } else {
$this->app->DB->Update("UPDATE rechnung SET mahnwesen='$mahnwesen', mahnwesenfestsetzen='$mahnwesenfestsetzen', mahnwesen_internebemerkung='$mahnwesen_internebemerkung', mahnwesen_gesperrt='$mahnwesen_gesperrt',mahnwesen_datum='$mahnwesen_datum' WHERE id='$id' LIMIT 1");
}
}*/
}
if($status=='')
$this->app->DB->Update("UPDATE rechnung SET status='angelegt' WHERE id='$id' LIMIT 1");
@@ -1962,6 +1947,7 @@ class Rechnung extends GenRechnung
' &uuml;berein <input type="submit" name="resetextsoll" value="Festgeschriebene Summe zur&uuml;cksetzen" /></div></form>'
);
}
parent::RechnungEdit();
if($id > 0 && $this->app->DB->Select(
sprintf(
@@ -2076,7 +2062,8 @@ class Rechnung extends GenRechnung
public function RechnungList()
{
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='offen' WHERE zahlungsstatus=''");
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='offen' WHERE zahlungsstatus=''");
if($this->app->Secure->GetPOST('ausfuehren') && $this->app->erp->RechteVorhanden('rechnung', 'edit'))
{
@@ -2098,10 +2085,10 @@ class Rechnung extends GenRechnung
switch($aktion)
{
case 'bezahlt':
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='bezahlt', bezahlt_am = now(), ist=soll,mahnwesenfestsetzen='1',mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Manuell als bezahlt markiert am ".date('d.m.Y')."') WHERE id IN (".implode(', ',$auswahl).')');
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='bezahlt', bezahlt_am = now(), mahnwesenfestsetzen='1',mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Manuell als bezahlt markiert am ".date('d.m.Y')."') WHERE id IN (".implode(', ',$auswahl).')');
break;
case 'offen':
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='offen',bezahlt_am = NULL, ist='0',mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Manuell als bezahlt entfernt am ".date('d.m.Y')."') WHERE id IN (".implode(', ',$auswahl).')');
$this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='offen',bezahlt_am = NULL, mahnwesen_internebemerkung=CONCAT(mahnwesen_internebemerkung,'\r\n','Manuell als bezahlt entfernt am ".date('d.m.Y')."') WHERE id IN (".implode(', ',$auswahl).')');
break;
case 'mail':
$auswahl = $this->app->DB->SelectFirstCols(
@@ -2258,6 +2245,28 @@ class Rechnung extends GenRechnung
}
}
// refresh all open items
$openids = $this->app->DB->SelectArr("SELECT id, waehrung from rechnung WHERE zahlungsstatus = 'offen'");
foreach ($openids as $openid) {
$saldo = $this->app->erp->GetSaldoDokument($openid['id'],'rechnung');
if (!empty($saldo)) {
if ($saldo['waehrung'] == $openid['waehrung']) {
$sql = "UPDATE
rechnung
SET
ist = ".$saldo['betrag']."+soll,
zahlungsstatus = IF(".$saldo['betrag']." = 0,'bezahlt','offen')
WHERE id=".$openid['id'];
$this->app->DB->Update($sql);
}
}
else {
$this->app->DB->Update("UPDATE rechnung SET ist = null WHERE id=".$openid['id']);
}
}
$this->app->Tpl->Set('UEBERSCHRIFT','Rechnungen');
$backurl = $this->app->Secure->GetGET('backurl');
@@ -2712,4 +2721,48 @@ class Rechnung extends GenRechnung
return $this->app->DB->GetInsertID();
}
/**
* Build the html output for minidetail containing the payments
* @param bool $return
*
* @return string
*/
function RechnungZahlung($return=false)
{
$id = $this->app->Secure->GetGET('id');
$zahlungen = $this->app->erp->GetZahlungen($id,'rechnung');
if (!empty($zahlungen)) {
$et = new EasyTable($this->app);
$et->headings = array('Datum','Beleg','Betrag','W&auml;hrung');
foreach ($zahlungen as $zahlung) {
$row = array(
$zahlung['datum'],
"<a href=\"index.php?module=".$zahlung['doc_typ']."&action=edit&id=".$zahlung['doc_id']."\">
".ucfirst($zahlung['doc_typ'])."
".$zahlung['doc_info']."
</a>",
$zahlung['betrag'],
$zahlung['waehrung']
);
$et->AddRow($row);
}
$salden = $this->app->erp->GetSaldenDokument($id,'rechnung');
foreach ($salden as $saldo) {
$row = array(
'',
'<b>Saldo</b>',
"<b>".$saldo['betrag']."</b>",
"<b>".$saldo['waehrung']."</b>"
);
$et->AddRow($row);
}
return($et->DisplayNew('return',""));
}
}
}
+1 -1
View File
@@ -2241,7 +2241,7 @@ $this->app->Tpl->Add('TODOFORUSER',"<tr><td width=\"90%\">".$tmp[$i]['aufgabe'].
$this->app->Tpl->Add('TAB1',"Sie benutzen die kommerzielle Version von Xentral. Alle Rechte vorbehalten. Beachten Sie die Nutzungsbedinungen.<br><br>&copy; Copyright by Xentral ERP Software GmbH Augsburg");
}
else {
$this->app->Tpl->Add('TAB1','OpenXE is free open source software under AGPL-3.0 license, based on <a href="https://xentral.com" target="_blank">Xentral®</a> by Xentral&nbsp;ERP&nbsp;Software&nbsp;GmbH.<br><br><div class="info"><img src="themes/new/images/Xentral_ERP_Logo-200.png"><br>Das Logo und der Link zur Homepage <a href="https://xentral.biz" target=\_blank\>https://xentral.biz</a> d&uuml;rfen nicht entfernt werden.</div><br>&copy; Copyright by OpenXE project & Xentral ERP Software GmbH Augsburg');
$this->app->Tpl->Add('TAB1','OpenXE is free open source software under AGPL/EGPL license, based on <a href="https://xentral.com" target="_blank">Xentral®</a> by Xentral&nbsp;ERP&nbsp;Software&nbsp;GmbH.<br><br><div class="info"><img src="themes/new/images/Xentral_ERP_Logo-200.png"><br>Das Logo und der Link zur Homepage <a href="https://xentral.biz" target=\_blank\>https://xentral.biz</a> d&uuml;rfen nicht entfernt werden.</div><br>&copy; Copyright by OpenXE project & Xentral ERP Software GmbH Augsburg');
}
if($this->app->erp->isIoncube() && method_exists($this->app->erp, 'IoncubeProperty'))
-7
View File
@@ -1,7 +0,0 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitbdcab6487556631ed3c158e0e8422e44::getLoader();
@@ -1,445 +0,0 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath.'\\';
if (isset($this->prefixDirsPsr4[$search])) {
foreach ($this->prefixDirsPsr4[$search] as $dir) {
$length = $this->prefixLengthsPsr4[$first][$search];
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}
-21
View File
@@ -1,21 +0,0 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -1,9 +0,0 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
@@ -1,10 +0,0 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'Fhp' => array($vendorDir . '/mschindler83/fints-hbci-php/lib'),
);
@@ -1,47 +0,0 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitbdcab6487556631ed3c158e0e8422e44
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitbdcab6487556631ed3c158e0e8422e44', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitbdcab6487556631ed3c158e0e8422e44', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitbdcab6487556631ed3c158e0e8422e44::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true);
return $loader;
}
}
@@ -1,26 +0,0 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInitbdcab6487556631ed3c158e0e8422e44
{
public static $prefixesPsr0 = array (
'F' =>
array (
'Fhp' =>
array (
0 => 'plugins/fints-hbci-php/vendor/mschindler83/fints-hbci-php/lib'
)
),
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixesPsr0 = ComposerStaticInitbdcab6487556631ed3c158e0e8422e44::$prefixesPsr0;
}, null, ClassLoader::class);
}
}
@@ -1,88 +0,0 @@
[
{
"name": "psr/log",
"version": "1.0.2",
"version_normalized": "1.0.2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"time": "2016-10-10T12:19:37+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"installation-source": "dist",
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
]
},
{
"name": "mschindler83/fints-hbci-php",
"version": "1.0.4",
"version_normalized": "1.0.4.0",
"source": {
"type": "git",
"url": "https://github.com/mschindler83/fints-hbci-php.git",
"reference": "e58cb825c178d4c39a8974a9dd93abbc8094551f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mschindler83/fints-hbci-php/zipball/e58cb825c178d4c39a8974a9dd93abbc8094551f",
"reference": "e58cb825c178d4c39a8974a9dd93abbc8094551f",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"psr/log": "~1.0"
},
"suggest": {
"monolog/monolog": "Allow sending log messages to a variety of different handlers"
},
"time": "2017-02-15T13:48:21+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-0": {
"Fhp": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHP Library for the protocols fints and hbci",
"homepage": "http://fints-hbci-php.markus-schindler.de"
}
]
File diff suppressed because it is too large Load Diff
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016 Markus Schindler <mail@markus-schindler.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,40 +0,0 @@
# FinTS HBCI PHP
[![Build Status](https://travis-ci.org/mschindler83/fints-hbci-php.svg?branch=master)](https://travis-ci.org/mschindler83/fints-hbci-php)
[![Latest Stable Version](https://poser.pugx.org/mschindler83/fints-hbci-php/v/stable)](https://packagist.org/packages/mschindler83/fints-hbci-php)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/mschindler83/fints-hbci-php/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/mschindler83/fints-hbci-php/?branch=master)
[![Monthly Downloads](https://poser.pugx.org/mschindler83/fints-hbci-php/d/monthly)](https://packagist.org/packages/mschindler83/fints-hbci-php)
[![License](https://poser.pugx.org/mschindler83/fints-hbci-php/license)](https://packagist.org/packages/mschindler83/fints-hbci-php)
A PHP library implementing the basics of the FinTS / HBCI protocol.
It can be used to fetch the balance of connected bank accounts and for fetching bank statements of accounts.
## Getting Started
Install via composer:
composer require mschindler83/fints-hbci-php
## How to use it
You can have a look at the "Samples" folder in this repository.
Just fill in the required data beginning from line 13 to 17 and run the script.
You can find the server information of your bank here:
https://www.hbci-zka.de/institute/institut_auswahl.htm
## Contribute
### Bank compatibility
This library can only work stable with *YOUR* help!
As I'm very limited in testing different banks it would be good to get some feedback from you all.
Feel free to create PR's for the [COMPATIBILITY.md](COMPATIBILITY.md) file where you can update the list of working banks.
### Code Style
If you plan to contribute to this library, please ensure that you stick with the PSR coding rules as close as you can (At least PSR-0 to PSR-4).
You can find the PHP Standard Recommendations [here](http://www.php-fig.org/psr/)
### Have fun!
@@ -1,18 +0,0 @@
<?php
namespace Fhp\Adapter;
use Fhp\Message\AbstractMessage;
/**
* Interface AdapterInterface
* @package Fhp\Adapter
*/
interface AdapterInterface
{
/**
* @param AbstractMessage $message
* @return string
*/
public function send(AbstractMessage $message);
}
@@ -1,106 +0,0 @@
<?php
namespace Fhp\Adapter;
use Fhp\Adapter\Exception\AdapterException;
use Fhp\Adapter\Exception\CurlException;
use Fhp\Message\AbstractMessage;
/**
* Class Curl
* @package Fhp\Adapter
*/
class Curl implements AdapterInterface
{
/**
* @var string
*/
protected $host;
/**
* @var int
*/
protected $port;
/**
* @var resource
*/
protected $curlHandle;
/**
* @var mixed
*/
protected $lastResponseInfo;
/**
* Curl constructor.
*
* @param string $host
* @param int $port
* @throws AdapterException
* @throws CurlException
*/
public function __construct($host, $port)
{
if (!is_integer($port) || (int) $port <= 0) {
throw new AdapterException('Invalid port number');
}
$this->host = (string) $host;
$this->port = (int) $port;
$this->curlHandle = curl_init();
curl_setopt($this->curlHandle, CURLOPT_SSLVERSION, 1);
curl_setopt($this->curlHandle, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($this->curlHandle, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($this->curlHandle, CURLOPT_USERAGENT, "FHP-lib");
curl_setopt($this->curlHandle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->curlHandle, CURLOPT_URL, $this->host);
curl_setopt($this->curlHandle, CURLOPT_CONNECTTIMEOUT, 15);
curl_setopt($this->curlHandle, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($this->curlHandle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($this->curlHandle, CURLOPT_ENCODING, '');
curl_setopt($this->curlHandle, CURLOPT_MAXREDIRS, 0);
curl_setopt($this->curlHandle, CURLOPT_TIMEOUT, 30);
curl_setopt($this->curlHandle, CURLOPT_HTTPHEADER, array("cache-control: no-cache", 'Content-Type: text/plain'));
}
/**
* @param AbstractMessage $message
* @return string
* @throws CurlException
*/
public function send(AbstractMessage $message)
{
curl_setopt($this->curlHandle, CURLOPT_POSTFIELDS, base64_encode($message->toString()));
$response = curl_exec($this->curlHandle);
$this->lastResponseInfo = curl_getinfo($this->curlHandle);
if (false === $response) {
throw new CurlException(
'Failed connection to ' . $this->host . ': ' . curl_error($this->curlHandle),
curl_errno($this->curlHandle),
null,
$this->lastResponseInfo
);
}
$statusCode = curl_getinfo($this->curlHandle, CURLINFO_HTTP_CODE);
if ($statusCode < 200 || $statusCode > 299) {
throw new CurlException('Bad response with status code ' . $statusCode, 0, null, $this->lastResponseInfo);
}
return base64_decode($response);
}
/**
* Gets curl info for last request / response.
*
* @return mixed
*/
public function getLastResponseInfo()
{
return $this->lastResponseInfo;
}
}
@@ -1,56 +0,0 @@
<?php
namespace Fhp\Adapter;
use Fhp\Adapter\Exception\AdapterException;
use Fhp\Message\AbstractMessage;
/**
* Class Debug Adapter.
*
* Use it to debug requests.
*
* @package Fhp\Adapter
*/
class Debug implements AdapterInterface
{
/**
* @var string
*/
protected $host;
/**
* @var int
*/
protected $port;
/**
* Debug constructor.
*
* @param $host
* @param $port
* @throws AdapterException
*/
public function __construct($host, $port)
{
if (!is_integer($port) || (int) $port <= 0) {
throw new AdapterException('Invalid port number');
}
$this->host = (string) $host;
$this->port = (int) $port;
}
/**
* Should return a dummy response body.
*
* @param AbstractMessage $message
* @return string
*/
public function send(AbstractMessage $message)
{
/* @todo Implement me
* return file_get_contents(__DIR__ . '/../../../develop/accounts_response.txt');
*/
}
}
@@ -1,12 +0,0 @@
<?php
namespace Fhp\Adapter\Exception;
/**
* Class AdapterException
* @package Fhp\Adapter\Exception
*/
class AdapterException extends \Exception
{
}
@@ -1,40 +0,0 @@
<?php
namespace Fhp\Adapter\Exception;
/**
* Class CurlException
* @package Fhp\Adapter\Exception
*/
class CurlException extends AdapterException
{
/**
* @var mixed
*/
protected $curlInfo;
/**
* CurlException constructor.
*
* @param string $message
* @param int $code
* @param \Exception|null $previous
* @param mixed $curlInfo
*/
public function __construct($message, $code = 0, \Exception $previous = null, $curlInfo)
{
parent::__construct($message, $code, $previous);
$this->curlInfo = $curlInfo;
}
/**
* Gets the curl info from request / response.
*
* @return mixed
*/
public function getCurlInfo()
{
return $this->curlInfo;
}
}
@@ -1,46 +0,0 @@
<?php
namespace Fhp;
use Fhp\Adapter\AdapterInterface;
use Fhp\Message\AbstractMessage;
/**
* Class Connection
* @package Fhp
*/
class Connection
{
/**
* @var AdapterInterface
*/
protected $adapter;
/**
* Connection constructor.
* @param AdapterInterface $adapter
*/
public function __construct(AdapterInterface $adapter)
{
$this->adapter = $adapter;
}
/**
* Uses the configured adapter to send a message.
*
* @param AbstractMessage $message
* @return string
*/
public function send(AbstractMessage $message)
{
return iconv('ISO-8859-1', 'UTF-8', $this->adapter->send($message));
}
/**
* @return AdapterInterface
*/
public function getAdapter()
{
return $this->adapter;
}
}
@@ -1,56 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\Deg;
/**
* Class EncryptionAlgorithm.
*
* @package Fhp\DataElementGroups
*/
class EncryptionAlgorithm extends Deg
{
const TYPE_OSY = 2;
const OPERATION_MODE_CBC = 2;
const OPERATION_MODE_ISO_9796_1 = 16;
const OPERATION_MODE_ISO_9796_2 = 17;
const OPERATION_MODE_RSASSA_PKCS_RSAES_PKCS = 18;
const OPERATION_MODE_RSASSA_PSS = 19;
const OPERATION_MODE_999 = 999;
const ALGORITHM_2_KEY_TRIPLE_DES = 13;
const ALGORITHM_AES_256 = 14;
const DEFAULT_ALGORITHM_IV = '@8@00000000';
const ALGORITHM_KEY_TYPE_SYM_SYM = 5;
const ALGORITHM_KEY_TYPE_SYM_PUB = 6;
const ALGORITHM_IV_DESCRIPTION_IVC = 1;
/**
* EncryptionAlgorithm constructor.
*
* @param int $type
* @param int $operationMode
* @param int $algorithm
* @param string $algorithmIv
* @param int $algorithmKeyType
* @param int $algorithmIvDescription
*/
public function __construct(
$type = self::TYPE_OSY,
$operationMode = self::OPERATION_MODE_CBC,
$algorithm = self::ALGORITHM_2_KEY_TRIPLE_DES,
$algorithmIv = self::DEFAULT_ALGORITHM_IV,
$algorithmKeyType = self::ALGORITHM_KEY_TYPE_SYM_SYM,
$algorithmIvDescription = self::ALGORITHM_IV_DESCRIPTION_IVC
) {
$this->addDataElement($type);
$this->addDataElement($operationMode);
$this->addDataElement($algorithm);
$this->addDataElement($algorithmIv);
$this->addDataElement($algorithmKeyType);
$this->addDataElement($algorithmIvDescription);
}
}
@@ -1,42 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\Deg;
/**
* Class HashAlgorithm.
*
* @package Fhp\DataElementGroups
*/
class HashAlgorithm extends Deg
{
const HASH_ALGORITHM_USAGE_OHA = 1; // Owner Hashing (OHA)
const HASH_ALGORITHM_SHA_1 = 1;
const HASH_ALGORITHM_X = 2;
const HASH_ALGORITHM_SHA_256 = 3;
const HASH_ALGORITHM_SHA_384 = 4;
const HASH_ALGORITHM_SHA_512 = 5;
const HASH_ALGORITHM_SHA_256_256 = 6;
const HASH_ALGORITHM_NEGOTIATE = 999;
const HASH_ALGORITHM_PARAM_DESCRIPTION_IVC = 1;
/**
* HashAlgorithm constructor.
*
* @param int $hashAlgorithmUsage
* @param int $hashAlgorithm
* @param int $hashAlgorithmParamDescription
*/
public function __construct(
$hashAlgorithmUsage = self::HASH_ALGORITHM_USAGE_OHA,
$hashAlgorithm = self::HASH_ALGORITHM_NEGOTIATE,
$hashAlgorithmParamDescription = self::HASH_ALGORITHM_PARAM_DESCRIPTION_IVC
) {
$this->addDataElement($hashAlgorithmUsage);
$this->addDataElement($hashAlgorithm);
$this->addDataElement($hashAlgorithmParamDescription);
}
}
@@ -1,35 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\DataTypes\Kik;
use Fhp\Deg;
/**
* Class KeyName.
* @package Fhp\DataElementGroups
*/
class KeyName extends Deg
{
const KEY_TYPE_DS_KEY = 'D';
const KEY_TYPE_SIGNATURE = 'S';
const KEY_TYPE_CHIFFRE = 'V';
/**
* KeyName constructor.
*
* @param string $countryCode
* @param string $bankCode
* @param string $userName
* @param string $keyType
*/
public function __construct($countryCode, $bankCode, $userName, $keyType = self::KEY_TYPE_CHIFFRE)
{
$kik = new Kik($countryCode, $bankCode);
$this->addDataElement($kik->toString());
$this->addDataElement($userName);
$this->addDataElement($keyType);
$this->addDataElement(0);
$this->addDataElement(0);
}
}
@@ -1,36 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\Deg;
/**
* Class SecurityDateTime.
* @package Fhp\DataElementGroups
*/
class SecurityDateTime extends Deg
{
/**
* Sicherheitszeitstempel (STS)
*/
const DATETIME_TYPE_STS = 1;
/**
* Certificate Revocation Time (CRT)
*/
const DATETIME_TYPE_CRT = 6;
/**
* SecurityDateTime constructor.
*
* @param int $type
* @param \DateTime|null $dateTime
*/
public function __construct($type = self::DATETIME_TYPE_STS, \DateTime $dateTime = null)
{
$date = null == $dateTime ? new \DateTime() : $dateTime;
$this->addDataElement($type);
$this->addDataElement($date->format('Ymd'));
$this->addDataElement($date->format('His'));
}
}
@@ -1,28 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\Deg;
/**
* Class SecurityIdentificationDetails
* @package Fhp\DataElementGroups
*/
class SecurityIdentificationDetails extends Deg
{
const PARTY_MS = 1; // sender
const CID_NONE = '';
/**
* SecurityIdentificationDetails constructor.
*
* @param string $cid
* @param int $systemId
*/
public function __construct($cid = self::CID_NONE, $systemId = 0)
{
$this->addDataElement(static::PARTY_MS);
$this->addDataElement($cid);
$this->addDataElement($systemId);
}
}
@@ -1,28 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\Deg;
/**
* Class SecurityProfile.
* @package Fhp\DataElementGroups
*/
class SecurityProfile extends Deg
{
const PROFILE_PIN = 'PIN';
const PROFILE_VERSION_1 = 1; // Ein-Schritt Tanverfahren
const PROFILE_VERSION_2 = 2; // Zwei-Schritt Tanverfahren
/**
* SecurityProfile constructor.
*
* @param $securityProceduresCode
* @param $securityProceduresVersion
*/
public function __construct($securityProceduresCode, $securityProceduresVersion)
{
$this->addDataElement($securityProceduresCode);
$this->addDataElement($securityProceduresVersion);
}
}
@@ -1,41 +0,0 @@
<?php
namespace Fhp\DataElementGroups;
use Fhp\Deg;
/**
* Class SignatureAlgorithm.
* @package Fhp\DataElementGroups
*/
class SignatureAlgorithm extends Deg
{
const SIG_ALGO_USAGE_OSG = 6; // Owner Signing (OSG)
const SIG_ALGO_DES = 1;
const SIG_ALGO_RSA = 10;
const OPERATION_MODE_CBC = 2;
const OPERATION_MODE_ISO_9796_1 = 16;
const OPERATION_MODE_ISO_9796_2 = 17;
const OPERATION_MODE_RSASSA_PKCS_RSAES_PKCS = 18;
const OPERATION_MODE_RSASSA_PSS = 19;
const OPERATION_MODE_999 = 999;
/**
* SignatureAlgorithm constructor.
*
* @param int $sigAlgoUsage
* @param int $sigAlgo
* @param int $operationMode
*/
public function __construct(
$sigAlgoUsage = self::SIG_ALGO_USAGE_OSG,
$sigAlgo = self::SIG_ALGO_RSA,
$operationMode = self::OPERATION_MODE_ISO_9796_1
) {
$this->addDataElement($sigAlgoUsage);
$this->addDataElement($sigAlgo);
$this->addDataElement($operationMode);
}
}
@@ -1,66 +0,0 @@
<?php
namespace Fhp\DataTypes;
/**
* Class Bin
* @package Fhp\DataTypes
*/
class Bin
{
/**
* @var string
*/
protected $string;
/**
* Bin constructor.
*
* @param string $string
*/
public function __construct($string)
{
$this->string = $string;
}
/**
* Sets the binary data.
*
* @param string $data
* @return $this
*/
public function setData($data)
{
$this->string = $data;
return $this;
}
/**
* Gets the binary data.
*
* @return string
*/
public function getData()
{
return $this->string;
}
/**
* Convert to string.
*
* @return string
*/
public function toString()
{
return '@' . strlen($this->string) . '@' . $this->string;
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
@@ -1,56 +0,0 @@
<?php
namespace Fhp\DataTypes;
/**
* Class Dat
* @package Fhp\DataTypes
*/
class Dat
{
/**
* @var \DateTime
*/
protected $value;
/**
* Dat constructor.
* @param \DateTime $dateTime
*/
public function __construct(\DateTime $dateTime)
{
$this->value = $dateTime;
}
/**
* @param \DateTime $date
*/
public function setDate(\DateTime $date)
{
$this->value = $date;
}
/**
* @return \DateTime
*/
public function getDate()
{
return $this->value;
}
/**
* @return string
*/
public function toString()
{
return $this->value->format('Ymd');
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
@@ -1,48 +0,0 @@
<?php
namespace Fhp\DataTypes;
/**
* Class Kik
* @package Fhp\DataTypes
*/
class Kik
{
/**
* @var string
*/
protected $countryCode;
/**
* @var string
*/
protected $bankCode;
/**
* Kik constructor.
*
* @param string $countryCode
* @param string $bankCode
*/
public function __construct($countryCode, $bankCode)
{
$this->countryCode = (string) $countryCode;
$this->bankCode = (string) $bankCode;
}
/**
* @return string
*/
public function toString()
{
return $this->countryCode . ':' . $this->bankCode;
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
@@ -1,76 +0,0 @@
<?php
namespace Fhp\DataTypes;
/**
* Class Kti (Kontoverbindung International)
*
* @link http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Messages_Geschaeftsvorfaelle_2015-08-07_final_version.pdf
* Section: B.3.2
* @package Fhp\DataTypes
*/
class Kti
{
/**
* @var string
*/
protected $iban;
/**
* @var string
*/
protected $bic;
/**
* @var string
*/
protected $accountNumber;
/**
* @var string
*/
protected $subAccountFeature;
/**
* @var Kik
*/
protected $kik;
/**
* Kti constructor.
*
* @param string $iban
* @param string $bic
* @param string $accountNumber
* @param string $subAccountFeature
* @param Kik $kik
*/
public function __construct($iban, $bic, $accountNumber, $subAccountFeature, Kik $kik)
{
$this->iban = $iban;
$this->bic = $bic;
$this->accountNumber = $accountNumber;
$this->subAccountFeature = $subAccountFeature;
$this->kik = $kik;
}
/**
* @return string
*/
public function toString()
{
return $this->iban . ':'
. $this->bic . ':'
. $this->accountNumber . ':'
. $this->subAccountFeature . ':'
. (string) $this->kik;
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
@@ -1,58 +0,0 @@
<?php
namespace Fhp\DataTypes;
/**
* Class Ktv (Kontoverbindung)
*
* @link http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Messages_Geschaeftsvorfaelle_2015-08-07_final_version.pdf
* Section: B.3.1
* @package Fhp\DataTypes
*/
class Ktv
{
/**
* @var string
*/
protected $accountNumber;
/**
* @var string
*/
protected $subAccountFeature;
/**
* @var Kik
*/
protected $kik;
/**
* Ktv constructor.
*
* @param string $accountNumber
* @param string $subAccountFeature
* @param Kik $kik
*/
public function __construct($accountNumber, $subAccountFeature, Kik $kik)
{
$this->accountNumber = $accountNumber;
$this->subAccountFeature = $subAccountFeature;
$this->kik = $kik;
}
/**
* @return string
*/
public function toString()
{
return $this->accountNumber . ':' . $this->subAccountFeature . ':' . (string) $this->kik;
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
@@ -1,36 +0,0 @@
<?php
namespace Fhp;
/**
* Class Deg (Data Element Group)
* @package Fhp
*/
class Deg
{
/** @var array */
protected $dataElements = array();
/**
* Adds a data element to the data element group.
*
* @param mixed $value
*/
public function addDataElement($value)
{
$this->dataElements[] = $value;
}
public function toString()
{
return (string) implode(':', $this->dataElements);
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
}
@@ -1,339 +0,0 @@
<?php
namespace Fhp\Dialog;
use Fhp\Adapter\Exception\AdapterException;
use Fhp\Adapter\Exception\CurlException;
use Fhp\Connection;
use Fhp\Dialog\Exception\FailedRequestException;
use Fhp\Message\AbstractMessage;
use Fhp\Message\Message;
use Fhp\Response\Initialization;
use Fhp\Response\Response;
use Fhp\Segment\HKEND;
use Fhp\Segment\HKIDN;
use Fhp\Segment\HKSYN;
use Fhp\Segment\HKVVB;
/**
* Class Dialog
* @package Fhp\Dialog
*/
class Dialog
{
const DEFAULT_COUNTRY_CODE = 280;
/**
* @var Connection
*/
protected $connection;
/**
* @var int
*/
protected $messageNumber = 1;
/**
* @var int
*/
protected $dialogId = 0;
/**
* @var int|string
*/
protected $systemId = 0;
/**
* @var string
*/
protected $bankCode;
/**
* @var string
*/
protected $username;
/**
* @var string
*/
protected $pin;
/**
* @var string
*/
protected $bankName;
/**
* @var array
*/
protected $supportedTanMechanisms = array();
/**
* @var int
*/
protected $hksalVersion = 6;
/**
* @var int
*/
protected $hkkazVersion = 6;
/**
* Dialog constructor.
*
* @param Connection $connection
* @param string $bankCode
* @param string $username
* @param string $pin
* @param string $systemId
*/
public function __construct(Connection $connection, $bankCode, $username, $pin, $systemId)
{
$this->connection = $connection;
$this->bankCode = $bankCode;
$this->username = $username;
$this->pin = $pin;
$this->systemId = $systemId;
}
/**
* @param AbstractMessage $message
* @return Response
* @throws AdapterException
* @throws CurlException
* @throws FailedRequestException
*/
public function sendMessage(AbstractMessage $message)
{
try {
$message->setMessageNumber($this->messageNumber);
$message->setDialogId($this->dialogId);
$result = $this->connection->send($message);
$this->messageNumber++;
$response = new Response($result);
$this->handleResponse($response);
if (!$response->isSuccess()) {
$summary = $response->getMessageSummary();
$ex = new FailedRequestException($summary);
throw $ex;
}
return $response;
} catch (AdapterException $e) {
if ($e instanceof CurlException) {
}
throw $e;
}
}
/**
* @param Response $response
*/
protected function handleResponse(Response $response)
{
$summary = $response->getMessageSummary();
$segSum = $response->getSegmentSummary();
foreach ($summary as $code => $message) {
$this->logMessage('HIRMG', $code, $message);
}
foreach ($segSum as $code => $message) {
$this->logMessage('HIRMS', $code, $message);
}
}
/**
* @param string $type
* @param string $code
* @param $message
*/
protected function logMessage($type, $code, $message)
{
}
/**
* Gets the dialog ID.
*
* @return integer
*/
public function getDialogId()
{
return $this->dialogId;
}
/**
* Gets the current message number.
*
* @return int
*/
public function getMessageNumber()
{
return $this->messageNumber;
}
/**
* Gets the system ID.
*
* @return int|string
*/
public function getSystemId()
{
return $this->systemId;
}
/**
* Gets all supported TAN mechanisms.
*
* @return array
*/
public function getSupportedPinTanMechanisms()
{
return $this->supportedTanMechanisms;
}
/**
* Gets the max possible HKSAL version.
*
* @return int
*/
public function getHksalMaxVersion()
{
return $this->hksalVersion;
}
/**
* Gets the max possible HKKAZ version.
*
* @return int
*/
public function getHkkazMaxVersion()
{
return $this->hkkazVersion;
}
/**
* Gets the bank name.
*
* @return string
*/
public function getBankName()
{
return $this->bankName;
}
/**
* Initializes a dialog.
*
* @return string|null
* @throws AdapterException
* @throws CurlException
* @throws FailedRequestException
* @throws \Exception
*/
public function initDialog()
{
$identification = new HKIDN(3, $this->bankCode, $this->username, $this->systemId);
$prepare = new HKVVB(4, HKVVB::DEFAULT_BPD_VERSION, HKVVB::DEFAULT_UPD_VERSION, HKVVB::LANG_DEFAULT);
$message = new Message(
$this->bankCode,
$this->username,
$this->pin,
$this->systemId,
0,
1,
array($identification, $prepare),
array(AbstractMessage::OPT_PINTAN_MECH => $this->supportedTanMechanisms)
);
$response = $this->sendMessage($message)->rawResponse;
$result = new Initialization($response);
$this->dialogId = $result->getDialogId();
return $this->dialogId;
}
/**
* Sends sync request.
*
* @return string
* @throws AdapterException
* @throws CurlException
* @throws FailedRequestException
* @throws \Exception
*/
public function syncDialog()
{
$this->messageNumber = 1;
$this->systemId = 0;
$this->dialogId = 0;
$identification = new HKIDN(3, $this->bankCode, $this->username, 0);
$prepare = new HKVVB(4, HKVVB::DEFAULT_BPD_VERSION, HKVVB::DEFAULT_UPD_VERSION, HKVVB::LANG_DEFAULT);
$sync = new HKSYN(5);
$syncMsg = new Message(
$this->bankCode,
$this->username,
$this->pin,
$this->systemId,
$this->dialogId,
$this->messageNumber,
array($identification, $prepare, $sync)
);
$response = $this->sendMessage($syncMsg);
// save BPD (Bank Parameter Daten)
$this->systemId = $response->getSystemId();
$this->dialogId = $response->getDialogId();
$this->bankName = $response->getBankName();
// max version for segment HKSAL (Saldo abfragen)
$this->hksalVersion = $response->getHksalMaxVersion();
$this->supportedTanMechanisms = $response->getSupportedTanMechanisms();
// max version for segment HKKAZ (Kontoumsätze anfordern / Zeitraum)
$this->hkkazVersion = $response->getHkkazMaxVersion();
$this->endDialog();
return $response->rawResponse;
}
/**
* Ends a previous started dialog.
*
* @return string
* @throws AdapterException
* @throws CurlException
* @throws FailedRequestException
*/
public function endDialog()
{
$endMsg = new Message(
$this->bankCode,
$this->username,
$this->pin,
$this->systemId,
$this->dialogId,
$this->messageNumber,
array(
new HKEND(3, $this->dialogId)
)
);
$response = $this->sendMessage($endMsg);
$this->dialogId = 0;
$this->messageNumber = 1;
return $response->rawResponse;
}
}
@@ -1,96 +0,0 @@
<?php
namespace Fhp\Dialog\Exception;
/**
* Class FailedRequestException.
*
* Transforms HBCI error to exception.
*
* @package Fhp\Dialog\Exception
*/
class FailedRequestException extends \Exception
{
/**
* @var array
*/
protected $summary = array();
/**
* @var int
*/
protected $responseCode = 0;
/**
* @var string
*/
protected $responseMessage;
/**
* FailedRequestException constructor.
*
* @param array $summary
*/
public function __construct(array $summary)
{
$this->summary = $summary;
$keys = array_keys($summary);
$this->responseCode = 0;
$this->responseMessage = 'Unknown error';
if (count($summary) == 1) {
$this->responseCode = (int) $keys[0];
$this->responseMessage = array_shift($summary);
} elseif (count($summary) > 1) {
foreach ($summary as $scode => $smsg) {
if (0 === strpos($smsg, '*')) {
$this->responseCode = (int) $scode;
$this->responseMessage = substr($smsg, 1);
}
}
}
parent::__construct('Request Failed: ' . $this->responseMessage, $this->responseCode);
}
/**
* @return array
*/
public function getCodes()
{
return array_keys($this->summary);
}
/**
* @return array
*/
public function getSummary()
{
return $this->summary;
}
/**
* @return int
*/
public function getResponseCode()
{
return $this->responseCode;
}
/**
* @return string
*/
public function getResponseMessage()
{
return $this->responseMessage;
}
/**
* @return string
*/
public function getResponseMessages()
{
return implode(', ', $this->summary);
}
}
@@ -1,418 +0,0 @@
<?php
namespace Fhp;
use Fhp\Adapter\AdapterInterface;
use Fhp\Adapter\Curl;
use Fhp\DataTypes\Kik;
use Fhp\DataTypes\Kti;
use Fhp\DataTypes\Ktv;
use Fhp\Dialog\Dialog;
use Fhp\Message\AbstractMessage;
use Fhp\Message\Message;
use Fhp\Model\SEPAAccount;
use Fhp\Response\GetAccounts;
use Fhp\Response\GetSaldo;
use Fhp\Response\GetSEPAAccounts;
use Fhp\Response\GetStatementOfAccount;
use Fhp\Segment\HKKAZ;
use Fhp\Segment\HKSAL;
use Fhp\Segment\HKSPA;
/**
* Class FinTs.
*
* @package Fhp
*/
class FinTs
{
const DEFAULT_COUNTRY_CODE = 280;
/** @var string */
protected $server;
/** @var int */
protected $port;
/** @var string */
protected $bankCode;
/** @var string */
protected $username;
/** @var string */
protected $pin;
/** @var Connection */
protected $connection;
/** @var AdapterInterface */
protected $adapter;
/** @var int */
protected $systemId = 0;
/** @var string */
protected $bankName;
/**
* FinTs constructor.
* @param string $server
* @param int $port
* @param string $bankCode
* @param string $username
* @param string $pin
*/
public function __construct(
$server,
$port,
$bankCode,
$username,
$pin
) {
$this->server = $server;
$this->port = $port;
// escaping of bank code not really needed here as it should
// never have special chars. But we just do it to ensure
// that the request will not get messed up and the user
// can receive a valid error response from the HBCI server.
$this->bankCode = $this->escapeString($bankCode);
// Here, escaping is needed for usernames or pins with
// HBCI special chars.
$this->username = $this->escapeString($username);
$this->pin = $this->escapeString($pin);
$this->adapter = new Curl($this->server, $this->port);
$this->connection = new Connection($this->adapter);
}
/**
* Sets the adapter to use.
*
* @param AdapterInterface $adapter
*/
public function setAdapter(AdapterInterface $adapter)
{
$this->adapter = $adapter;
$this->connection = new Connection($this->adapter);
}
/**
* Gets array of all accounts.
*
* @return Model\Account[]
*/
public function getAccounts()
{
$dialog = $this->getDialog();
$result = $dialog->syncDialog();
$this->bankName = $dialog->getBankName();
$accounts = new GetAccounts($result);
return $accounts->getAccountsArray();
}
/**
* Gets array of all SEPA Accounts.
*
* @return Model\SEPAAccount[]
* @throws Adapter\Exception\AdapterException
* @throws Adapter\Exception\CurlException
*/
public function getSEPAAccounts()
{
$dialog = $this->getDialog();
$dialog->syncDialog();
$dialog->initDialog();
$message = $this->getNewMessage(
$dialog,
array(new HKSPA(3)),
array(AbstractMessage::OPT_PINTAN_MECH => $dialog->getSupportedPinTanMechanisms())
);
$result = $dialog->sendMessage($message);
$dialog->endDialog();
$sepaAccounts = new GetSEPAAccounts($result->rawResponse);
return $sepaAccounts->getSEPAAccountsArray();
}
/**
* Gets the bank name.
*
* @return string
*/
public function getBankName()
{
if (null == $this->bankName) {
$this->getDialog()->syncDialog();
}
return $this->bankName;
}
/**
* Gets statement of account.
*
* @param SEPAAccount $account
* @param \DateTime $from
* @param \DateTime $to
* @return Model\StatementOfAccount\StatementOfAccount|null
* @throws \Exception
*/
public function getStatementOfAccount(SEPAAccount $account, \DateTime $from, \DateTime $to)
{
$responses = array();
$dialog = $this->getDialog();
$dialog->syncDialog();
$dialog->initDialog();
$message = $this->createStateOfAccountMessage($dialog, $account, $from, $to, null);
$response = $dialog->sendMessage($message);
$touchdowns = $response->getTouchdowns($message);
$soaResponse = new GetStatementOfAccount($response->rawResponse);
$responses[] = $soaResponse->getRawMt940();
$touchdownCounter = 1;
while (isset($touchdowns[HKKAZ::NAME])) {
$message = $this->createStateOfAccountMessage(
$dialog,
$account,
$from,
$to,
$touchdowns[HKKAZ::NAME]
);
$r = $dialog->sendMessage($message);
$touchdowns = $r->getTouchDowns($message);
$soaResponse = new GetStatementOfAccount($r->rawResponse);
$responses[] = $soaResponse->getRawMt940();
}
$dialog->endDialog();
return GetStatementOfAccount::createModelFromRawMt940(implode('', $responses));
}
/**
* Helper method to create a "Statement of Account Message".
*
* @param Dialog $dialog
* @param SEPAAccount $account
* @param \DateTime $from
* @param \DateTime $to
* @param string|null $touchdown
* @return Message
* @throws \Exception
*/
protected function createStateOfAccountMessage(
Dialog $dialog,
SepaAccount $account,
\DateTime $from,
\DateTime $to,
$touchdown = null
) {
// version 4, 5, 6, 7
// version 5
/*
1 Segmentkopf DEG M 1
2 Kontoverbindung Auftraggeber DEG ktv # M 1
3 Alle Konten DE jn # M 1
4 Von Datum DE dat # K 1
5 Bis Datum DE dat # K 1
6 Maximale Anzahl Einträge DE num ..4 K 1 >0
7 Aufsetzpunkt DE an ..35 K 1
*/
// version 6
/*
1 Segmentkopf 1 DEG M 1
2 Kontoverbindung Auftraggeber 2 DEG ktv # M 1
3 Alle Konten 1 DE jn # M 1
4 Von Datum 1 DE dat # O 1
5 Bis Datum 1 DE dat # O 1
6 Maximale Anzahl Einträge 1 DE num ..4 C 1 >0
7 Aufsetzpunkt 1 DE an ..35 C 1
*/
// version 7
/*
1 Segmentkopf 1 DEG M 1
2 Kontoverbindung international 1 DEG kti # M 1
3 Alle Konten 1 DE jn # M 1
4 Von Datum 1 DE dat # O 1
5 Bis Datum 1 DE dat # O 1
6 Maximale Anzahl Einträge 1 DE num ..4 C 1 >0
7 Aufsetzpunkt 1 DE an ..35 C 1
*/
switch ($dialog->getHkkazMaxVersion()) {
case 4:
case 5:
$konto = new Deg();
$konto->addDataElement($account->getAccountNumber());
$konto->addDataElement($account->getSubAccount());
$konto->addDataElement(static::DEFAULT_COUNTRY_CODE);
$konto->addDataElement($account->getBlz());
break;
case 6:
$konto = new Ktv(
$account->getAccountNumber(),
$account->getSubAccount(),
new Kik(280, $account->getBlz())
);
break;
case 7:
$konto = new Kti(
$account->getIban(),
$account->getBic(),
$account->getAccountNumber(),
$account->getSubAccount(),
new Kik(280, $account->getBlz())
);
break;
default:
throw new \Exception('Unsupported HKKAZ version: ' . $dialog->getHkkazMaxVersion());
}
$message = $this->getNewMessage(
$dialog,
array(
new HKKAZ(
$dialog->getHkkazMaxVersion(),
3,
$konto,
HKKAZ::ALL_ACCOUNTS_N,
$from,
$to,
$touchdown
)
),
array(AbstractMessage::OPT_PINTAN_MECH => $dialog->getSupportedPinTanMechanisms())
);
return $message;
}
/**
* Gets the saldo of given SEPAAccount.
*
* @param SEPAAccount $account
* @return Model\Saldo|null
* @throws Adapter\Exception\AdapterException
* @throws Adapter\Exception\CurlException
* @throws \Exception
*/
public function getSaldo(SEPAAccount $account)
{
$dialog = $this->getDialog();
$dialog->syncDialog();
$dialog->initDialog();
switch ((int) $dialog->getHksalMaxVersion()) {
case 4:
case 5:
$hksalAccount = new Deg(
$account->getAccountNumber(),
$account->getSubAccount(),
static::DEFAULT_COUNTRY_CODE, $account->getBlz()
);
$hksalAccount->addDataElement($account->getAccountNumber());
$hksalAccount->addDataElement($account->getSubAccount());
$hksalAccount->addDataElement(static::DEFAULT_COUNTRY_CODE);
$hksalAccount->addDataElement($account->getBlz());
break;
case 6:
$hksalAccount = new Ktv(
$account->getAccountNumber(),
$account->getSubAccount(),
new Kik(280, $account->getBlz())
);
break;
case 7:
$hksalAccount = new Kti(
$account->getIban(),
$account->getBic(),
$account->getAccountNumber(),
$account->getSubAccount(),
new Kik(280, $account->getBlz())
);
break;
default:
throw new \Exception('Unsupported HKSAL version: ' . $dialog->getHksalMaxVersion());
}
$message = new Message(
$this->bankCode,
$this->username,
$this->pin,
$dialog->getSystemId(),
$dialog->getDialogId(),
$dialog->getMessageNumber(),
array(
new HKSAL($dialog->getHksalMaxVersion(), 3, $hksalAccount, HKSAL::ALL_ACCOUNTS_N)
),
array(
AbstractMessage::OPT_PINTAN_MECH => $dialog->getSupportedPinTanMechanisms()
)
);
$response = $dialog->sendMessage($message);
$response = new GetSaldo($response->rawResponse);
return $response->getSaldoModel();
}
/**
* Helper method to retrieve a pre configured message object.
* Factory for poor people :)
*
* @param Dialog $dialog
* @param array $segments
* @param array $options
* @return Message
*/
protected function getNewMessage(Dialog $dialog, array $segments, array $options)
{
return new Message(
$this->bankCode,
$this->username,
$this->pin,
$dialog->getSystemId(),
$dialog->getDialogId(),
$dialog->getMessageNumber(),
$segments,
$options
);
}
/**
* Helper method to retrieve a pre configured dialog object.
* Factory for poor people :)
*
* @return Dialog
*/
protected function getDialog()
{
return new Dialog(
$this->connection,
$this->bankCode,
$this->username,
$this->pin,
$this->systemId
);
}
/**
* Needed for escaping userdata.
* HBCI escape char is "?"
*
* @param string $string
* @return string
*/
protected function escapeString($string)
{
return str_replace(
array('?', '@', ':', '+', '\''),
array('??', '?@', '?:', '?+', '?\''),
$string
);
}
}
@@ -1,134 +0,0 @@
<?php
namespace Fhp\Message;
use Fhp\Segment\HNHBK;
use Fhp\Segment\SegmentInterface;
/**
* Class AbstractMessage
* @package Fhp\Message
*/
class AbstractMessage
{
const MSG_HEADER_SEGMENT = 'HNHBK';
const MSG_HEADER_VERSION = 3;
const MSG_HEADER_SEG_NUMBER = 1;
const MSG_HBCI_VERSION = '300';
const OPT_PINTAN_MECH = 'pintan_mechanism';
/**
* @var array
*/
protected $segments = array();
/**
* @var int
*/
protected $dialogId = 0;
/**
* @var int
*/
protected $messageNumber = 1;
/**
* Adds a segment to the message.
*
* @param SegmentInterface $segment
*/
protected function addSegment(SegmentInterface $segment)
{
$this->segments[] = $segment;
}
/**
* Gets all segments of a message.
*
* @return array
*/
public function getSegments()
{
return $this->segments;
}
/**
* Sets the dialog ID.
*
* @param $dialogId
*/
public function setDialogId($dialogId)
{
$this->dialogId = $dialogId;
}
/**
* Gets the dialog ID.
*
* @return int
*/
public function getDialogId()
{
return $this->dialogId;
}
/**
* Sets the message number.
*
* @param int $number
*/
public function setMessageNumber($number)
{
$this->messageNumber = (int) $number;
}
/**
* Gets the message number.
*
* @return int
*/
public function getMessageNumber()
{
return $this->messageNumber;
}
/**
* Transform message to HBCI string.
*
* @return string
*/
public function toString()
{
$string = (string) $this->buildMessageHeader();
foreach ($this->segments as $segment) {
$string .= (string) $segment;
}
return $string;
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
/**
* Builds the message header.
*
* @return HNHBK
*/
protected function buildMessageHeader()
{
$len = 0;
foreach ($this->segments as $segment) {
$len += strlen($segment);
}
return new HNHBK($len, $this->dialogId, $this->messageNumber);
}
}
@@ -1,196 +0,0 @@
<?php
namespace Fhp\Message;
use Fhp\DataElementGroups\SecurityProfile;
use Fhp\Segment\AbstractSegment;
use Fhp\Segment\HNHBS;
use Fhp\Segment\HNSHA;
use Fhp\Segment\HNSHK;
use Fhp\Segment\HNVSD;
use Fhp\Segment\HNVSK;
use Fhp\Segment\SegmentInterface;
/**
* Class Message.
*
* @package Fhp\Message
*/
class Message extends AbstractMessage
{
/**
* @var int
*/
protected $encryptedSegmentsCount = 0;
/**
* @var int
*/
protected $securityReference;
/**
* @var string
*/
protected $pin;
/**
* @var string
*/
protected $bankCode;
/**
* @var string
*/
protected $username;
/**
* @var string
*/
protected $systemId;
/**
* @var array
*/
protected $options;
/**
* @var int
*/
protected $profileVersion;
/**
* @var string
*/
protected $securityFunction;
/**
* @var array
*/
private $encryptedSegments = array();
/**
* @var HNVSD
*/
protected $encryptionEnvelop;
/**
* Message constructor.
* @param string $bankCode
* @param string $username
* @param string $pin
* @param $systemId
* @param int $dialogId
* @param int $messageNumber
* @param array $encryptedSegments
* @param array $options
*/
public function __construct(
$bankCode,
$username,
$pin,
$systemId,
$dialogId = 0,
$messageNumber = 0,
array $encryptedSegments = array(),
array $options = array()
) {
$this->securityReference = rand(1000000, 9999999);
$this->dialogId = $dialogId;
$this->messageNumber = $messageNumber;
$this->bankCode = $bankCode;
$this->username = $username;
$this->pin = $pin;
$this->systemId = $systemId;
$this->options = $options;
$this->profileVersion = SecurityProfile::PROFILE_VERSION_1;
$this->securityFunction = HNSHK::SECURITY_FUNC_999;
if (isset($options[static::OPT_PINTAN_MECH]) && !empty($this->options[static::OPT_PINTAN_MECH])) {
if (!in_array('999', $this->options[static::OPT_PINTAN_MECH])) {
$this->profileVersion = SecurityProfile::PROFILE_VERSION_2;
$this->securityFunction = $this->options[static::OPT_PINTAN_MECH][0];
}
}
$signatureHead = $this->buildSignatureHead();
$hnvsk = $this->buildEncryptionHead();
$this->addSegment($hnvsk);
$this->encryptionEnvelop = new HNVSD(999, '');
$this->addSegment($this->encryptionEnvelop);
$this->addEncryptedSegment($signatureHead);
foreach ($encryptedSegments as $es) {
$this->addEncryptedSegment($es);
}
$curCount = count($encryptedSegments) + 3;
$signatureEnd = new HNSHA($curCount, $this->securityReference, $this->pin);
$this->addEncryptedSegment($signatureEnd);
$this->addSegment(new HNHBS($curCount + 1, $this->messageNumber));
}
/**
* @return HNVSK
* @codeCoverageIgnore
*/
protected function buildEncryptionHead()
{
return new HNVSK(
998,
$this->bankCode,
$this->username,
$this->systemId,
HNVSK::SECURITY_SUPPLIER_ROLE_ISS,
HNVSK::DEFAULT_COUNTRY_CODE,
HNVSK::COMPRESSION_NONE,
$this->profileVersion
);
}
/**
* @return HNSHK
* @codeCoverageIgnore
*/
protected function buildSignatureHead()
{
return new HNSHK(
2,
$this->securityReference,
280, // country code
$this->bankCode,
$this->username,
$this->systemId,
$this->securityFunction,
HNSHK::SECURITY_BOUNDARY_SHM,
HNSHK::SECURITY_SUPPLIER_ROLE_ISS,
$this->profileVersion
);
}
/**
* Adds a encrypted segment to the message.
*
* @param SegmentInterface $segment
*/
protected function addEncryptedSegment(SegmentInterface $segment)
{
$this->encryptedSegmentsCount++;
$this->encryptedSegments[] = $segment;
$encodedData = $this->encryptionEnvelop->getEncodedData()->getData();
$encodedData .= (string) $segment;
$this->encryptionEnvelop->setEncodedData($encodedData);
}
/**
* Only for read-only access.
* @return AbstractSegment[]
*/
public function getEncryptedSegments()
{
return $this->encryptedSegments;
}
}
@@ -1,219 +0,0 @@
<?php
namespace Fhp\Model;
/**
* Class Account
* @package Fhp\Model
*/
class Account
{
/** @var string */
protected $id;
/** @var string */
protected $accountNumber;
/** @var string */
protected $bankCode;
/** @var string */
protected $iban;
/** @var string */
protected $customerId;
/** @var string */
protected $currency;
/** @var string */
protected $accountOwnerName;
/** @var string */
protected $accountDescription;
/**
* Get id
*
* @return mixed
*/
public function getId()
{
return $this->id;
}
/**
* Set id
*
* @param string $id
*
* @return $this
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Get accountNumber
*
* @return string
*/
public function getAccountNumber()
{
return $this->accountNumber;
}
/**
* Set accountNumber
*
* @param string $accountNumber
*
* @return $this
*/
public function setAccountNumber($accountNumber)
{
$this->accountNumber = (string) $accountNumber;
return $this;
}
/**
* Get bankCode
*
* @return string
*/
public function getBankCode()
{
return $this->bankCode;
}
/**
* Set bankCode
*
* @param string $bankCode
*
* @return $this
*/
public function setBankCode($bankCode)
{
$this->bankCode = (string) $bankCode;
return $this;
}
/**
* Get iban
*
* @return string
*/
public function getIban()
{
return $this->iban;
}
/**
* Set iban
*
* @param string $iban
*
* @return $this
*/
public function setIban($iban)
{
$this->iban = (string) $iban;
return $this;
}
/**
* Get customerId
*
* @return string
*/
public function getCustomerId()
{
return $this->customerId;
}
/**
* Set customerId
*
* @param string $customerId
*
* @return $this
*/
public function setCustomerId($customerId)
{
$this->customerId = (string) $customerId;
return $this;
}
/**
* Get currency
*
* @return string
*/
public function getCurrency()
{
return $this->currency;
}
/**
* Set currency
*
* @param string $currency
*
* @return $this
*/
public function setCurrency($currency)
{
$this->currency = (string) $currency;
return $this;
}
/**
* Get accountOwnerName
*
* @return string
*/
public function getAccountOwnerName()
{
return $this->accountOwnerName;
}
/**
* Set accountOwnerName
*
* @param string $accountOwnerName
*
* @return $this
*/
public function setAccountOwnerName($accountOwnerName)
{
$this->accountOwnerName = (string) $accountOwnerName;
return $this;
}
/**
* Get accountDescription
*
* @return string
*/
public function getAccountDescription()
{
return $this->accountDescription;
}
/**
* Set accountDescription
*
* @param string $accountDescription
*
* @return $this
*/
public function setAccountDescription($accountDescription)
{
$this->accountDescription = (string) $accountDescription;
return $this;
}
}
@@ -1,141 +0,0 @@
<?php
namespace Fhp\Model;
/**
* Class SEPAAccount
* @package Fhp\Model
*/
class SEPAAccount
{
/** @var string */
protected $iban;
/** @var string */
protected $bic;
/** @var string */
protected $accountNumber;
/** @var string */
protected $subAccount;
/** @var string */
protected $blz;
/**
* Get iban
*
* @return string
*/
public function getIban()
{
return $this->iban;
}
/**
* Set iban
*
* @param string $iban
*
* @return $this
*/
public function setIban($iban)
{
$this->iban = (string) $iban;
return $this;
}
/**
* Get bic
*
* @return string
*/
public function getBic()
{
return $this->bic;
}
/**
* Set bic
*
* @param string $bic
*
* @return $this
*/
public function setBic($bic)
{
$this->bic = (string) $bic;
return $this;
}
/**
* Get accountNumber
*
* @return string
*/
public function getAccountNumber()
{
return $this->accountNumber;
}
/**
* Set accountNumber
*
* @param string $accountNumber
*
* @return $this
*/
public function setAccountNumber($accountNumber)
{
$this->accountNumber = (string) $accountNumber;
return $this;
}
/**
* Get subAccount
*
* @return string
*/
public function getSubAccount()
{
return $this->subAccount;
}
/**
* Set subAccount
*
* @param string $subAccount
*
* @return $this
*/
public function setSubAccount($subAccount)
{
$this->subAccount = (string) $subAccount;
return $this;
}
/**
* Get blz
*
* @return string
*/
public function getBlz()
{
return $this->blz;
}
/**
* Set blz
*
* @param string $blz
*
* @return $this
*/
public function setBlz($blz)
{
$this->blz = (string) $blz;
return $this;
}
}
@@ -1,97 +0,0 @@
<?php
namespace Fhp\Model;
/**
* Class Saldo
* @package Fhp\Model
*/
class Saldo
{
/**
* @var string
*/
protected $currency;
/**
* @var float
*/
protected $amount;
/**
* @var \DateTime
*/
protected $valuta;
/**
* Get currency
*
* @return string
*/
public function getCurrency()
{
return $this->currency;
}
/**
* Set currency
*
* @param string $currency
*
* @return $this
*/
public function setCurrency($currency)
{
$this->currency = (string) $currency;
return $this;
}
/**
* Get amount
*
* @return float
*/
public function getAmount()
{
return $this->amount;
}
/**
* Set amount
*
* @param float $amount
*
* @return $this
*/
public function setAmount($amount)
{
$this->amount = (float) $amount;
return $this;
}
/**
* Get valuta
*
* @return \DateTime
*/
public function getValuta()
{
return $this->valuta;
}
/**
* Set valuta
*
* @param \DateTime $valuta
*
* @return $this
*/
public function setValuta(\DateTime $valuta)
{
$this->valuta = $valuta;
return $this;
}
}
@@ -1,134 +0,0 @@
<?php
namespace Fhp\Model\StatementOfAccount;
/**
* Class Statement
* @package Fhp\Model\StatementOfAccount
*/
class Statement
{
const CD_CREDIT = 'credit';
const CD_DEBIT = 'debit';
/**
* @var array of Transaction
*/
protected $transactions = array();
/**
* @var float
*/
protected $startBalance = 0.0;
/**
* @var string
*/
protected $creditDebit;
/**
* @var \DateTime|null
*/
protected $date;
/**
* Get transactions
*
* @return Transaction[]
*/
public function getTransactions()
{
return $this->transactions;
}
/**
* Set transactions
*
* @param array $transactions
*
* @return $this
*/
public function setTransactions(array $transactions = null)
{
$this->transactions = $transactions;
return $this;
}
public function addTransaction(Transaction $transaction)
{
$this->transactions[] = $transaction;
}
/**
* Get startBalance
*
* @return float
*/
public function getStartBalance()
{
return $this->startBalance;
}
/**
* Set startBalance
*
* @param float $startBalance
*
* @return $this
*/
public function setStartBalance($startBalance)
{
$this->startBalance = (float) $startBalance;
return $this;
}
/**
* Get creditDebit
*
* @return string
*/
public function getCreditDebit()
{
return $this->creditDebit;
}
/**
* Set creditDebit
*
* @param string|null $creditDebit
*
* @return $this
*/
public function setCreditDebit($creditDebit)
{
$this->creditDebit = $creditDebit;
return $this;
}
/**
* Get date
*
* @return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set date
*
* @param \DateTime $date
*
* @return $this
*/
public function setDate(\DateTime $date)
{
$this->date = $date;
return $this;
}
}
@@ -1,83 +0,0 @@
<?php
namespace Fhp\Model\StatementOfAccount;
/**
* Class StatementOfAccount
* @package Fhp\Model\StatementOfAccount
*/
class StatementOfAccount
{
/**
* @var Statement[]
*/
protected $statements = array();
/**
* Get statements
*
* @return Statement[]
*/
public function getStatements()
{
return $this->statements;
}
/**
* Set statements
*
* @param array $statements
*
* @return $this
*/
public function setStatements(array $statements = null)
{
$this->statements = null == $statements ? array() : $statements;
return $this;
}
/**
* @param Statement $statement
*/
public function addStatement(Statement $statement)
{
$this->statements[] = $statement;
}
/**
* Gets statement for given date.
*
* @param string|\DateTime $date
* @return Statement|null
*/
public function getStatementForDate($date)
{
if (is_string($date)) {
$date = new \DateTime($date);
}
foreach ($this->statements as $stmt) {
if ($stmt->getDate() == $date) {
return $stmt;
}
}
return null;
}
/**
* Checks if a statement with given date exists.
*
* @param string|\DateTime $date
* @return bool
*/
public function hasStatementForDate($date)
{
if (is_string($date)) {
$date = new \DateTime($date);
}
return null !== $this->getStatementForDate($date);
}
}
@@ -1,359 +0,0 @@
<?php
namespace Fhp\Model\StatementOfAccount;
/**
* Class Transaction
* @package Fhp\Model\StatementOfAccount
*/
class Transaction
{
const CD_CREDIT = 'credit';
const CD_DEBIT = 'debit';
/**
* @var \DateTime|null
*/
protected $bookingDate;
/**
* @var \DateTime|null
*/
protected $valutaDate;
/**
* @var float
*/
protected $amount;
/**
* @var string
*/
protected $creditDebit;
/**
* @var string
*/
protected $bookingText;
/**
* @var string
*/
protected $description1;
/**
* @var string
*/
protected $description2;
/**
* Array keys are identifiers like "SVWZ" for the main description.
* @var array
*/
protected $structuredDescription;
/**
* @var string
*/
protected $bankCode;
/**
* @var string
*/
protected $accountNumber;
/**
* @var string
*/
protected $name;
/**
* Get booking date.
*
* @deprecated Use getBookingDate() instead
* @codeCoverageIgnore
* @return \DateTime|null
*/
public function getDate()
{
return $this->getBookingDate();
}
/**
* Get booking date
*
* @return \DateTime|null
*/
public function getBookingDate()
{
return $this->bookingDate;
}
/**
* Get date
*
* @return \DateTime|null
*/
public function getValutaDate()
{
return $this->valutaDate;
}
/**
* Set booking date
*
* @param \DateTime|null $date
*
* @return $this
*/
public function setBookingDate(\DateTime $date = null)
{
$this->bookingDate = $date;
return $this;
}
/**
* Set valuta date
*
* @param \DateTime|null $date
*
* @return $this
*/
public function setValutaDate(\DateTime $date = null)
{
$this->valutaDate = $date;
return $this;
}
/**
* Get amount
*
* @return float
*/
public function getAmount()
{
return $this->amount;
}
/**
* Set amount
*
* @param float $amount
*
* @return $this
*/
public function setAmount($amount)
{
$this->amount = (float) $amount;
return $this;
}
/**
* Get creditDebit
*
* @return string
*/
public function getCreditDebit()
{
return $this->creditDebit;
}
/**
* Set creditDebit
*
* @param string $creditDebit
*
* @return $this
*/
public function setCreditDebit($creditDebit)
{
$this->creditDebit = $creditDebit;
return $this;
}
/**
* Get bookingText
*
* @return string
*/
public function getBookingText()
{
return $this->bookingText;
}
/**
* Set bookingText
*
* @param string $bookingText
*
* @return $this
*/
public function setBookingText($bookingText)
{
$this->bookingText = (string) $bookingText;
return $this;
}
/**
* Get description1
*
* @return string
*/
public function getDescription1()
{
return $this->description1;
}
/**
* Set description1
*
* @param string $description1
*
* @return $this
*/
public function setDescription1($description1)
{
$this->description1 = (string) $description1;
return $this;
}
/**
* Get description2
*
* @return string
*/
public function getDescription2()
{
return $this->description2;
}
/**
* Set description2
*
* @param string $description2
*
* @return $this
*/
public function setDescription2($description2)
{
$this->description2 = (string) $description2;
return $this;
}
/**
* Get structuredDescription
*
* @return array
*/
public function getStructuredDescription()
{
return $this->structuredDescription;
}
/**
* Set structuredDescription
*
* @param array $structuredDescription
*
* @return $this
*/
public function setStructuredDescription($structuredDescription)
{
$this->structuredDescription = $structuredDescription;
return $this;
}
/**
* Get the main description (SVWZ)
*
* @return string
*/
public function getMainDescription()
{
if (array_key_exists('SVWZ', $this->structuredDescription)) {
return $this->structuredDescription['SVWZ'];
} else {
return "";
}
}
/**
* Get bankCode
*
* @return string
*/
public function getBankCode()
{
return $this->bankCode;
}
/**
* Set bankCode
*
* @param string $bankCode
*
* @return $this
*/
public function setBankCode($bankCode)
{
$this->bankCode = (string) $bankCode;
return $this;
}
/**
* Get accountNumber
*
* @return string
*/
public function getAccountNumber()
{
return $this->accountNumber;
}
/**
* Set accountNumber
*
* @param string $accountNumber
*
* @return $this
*/
public function setAccountNumber($accountNumber)
{
$this->accountNumber = (string) $accountNumber;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set name
*
* @param string $name
*
* @return $this
*/
public function setName($name)
{
$this->name = (string) $name;
return $this;
}
}
@@ -1,12 +0,0 @@
<?php
namespace Fhp\Parser\Exception;
/**
* Class MT940Exception
* @package Fhp\Parser\Exception
*/
class MT940Exception extends \Exception
{
}
@@ -1,229 +0,0 @@
<?php
namespace Fhp\Parser;
use Fhp\Parser\Exception\MT940Exception;
/**
* Class MT940
* @package Fhp\Parser
*/
class MT940
{
const TARGET_ARRAY = 0;
const CD_CREDIT = 'credit';
const CD_DEBIT = 'debit';
/** @var string */
protected $rawData;
/** @var string */
protected $soaDate;
/**
* MT940 constructor.
*
* @param string $rawData
*/
public function __construct($rawData)
{
$this->rawData = (string) $rawData;
}
/**
* @param string $target
* @return array
* @throws MT940Exception
*/
public function parse($target)
{
switch ($target) {
case static::TARGET_ARRAY:
return $this->parseToArray();
break;
default:
throw new MT940Exception('Invalid parse type provided');
}
}
/**
* @return array
* @throws MT940Exception
*/
protected function parseToArray()
{
// The divider can be either \r\n or @@
$divider = substr_count($this->rawData, "\r\n-") > substr_count($this->rawData, '@@-') ? "\r\n" : '@@';
$result = array();
$days = preg_split('%' . $divider . '-$%', $this->rawData);
foreach ($days as &$day) {
$day = explode($divider . ':', $day);
for ($i = 0, $cnt = count($day); $i < $cnt; $i++) {
// handle start balance
// 60F:C160401EUR1234,56
if (preg_match('/^60(F|M):/', $day[$i])) {
// remove 60(F|M): for better parsing
$day[$i] = substr($day[$i], 4);
$this->soaDate = $this->getDate(substr($day[$i], 1, 6));
if (!isset($result[$this->soaDate])) {
$result[$this->soaDate] = array('start_balance' => array());
}
$cdMark = substr($day[$i], 0, 1);
if ($cdMark == 'C') {
$result[$this->soaDate]['start_balance']['credit_debit'] = static::CD_CREDIT;
} elseif ($cdMark == 'D') {
$result[$this->soaDate]['start_balance']['credit_debit'] = static::CD_DEBIT;
}
$amount = str_replace(',', '.', substr($day[$i], 10));
$result[$this->soaDate]['start_balance']['amount'] = $amount;
} elseif (
// found transaction
// trx:61:1603310331DR637,39N033NONREF
0 === strpos($day[$i], '61:')
&& isset($day[$i + 1])
&& 0 === strpos($day[$i + 1], '86:')
) {
$transaction = substr($day[$i], 3);
$description = substr($day[$i + 1], 3);
if (!isset($result[$this->soaDate]['transactions'])) {
$result[$this->soaDate]['transactions'] = array();
}
// short form for better handling
$trx = &$result[$this->soaDate]['transactions'];
preg_match('/^\d{6}(\d{4})?(C|D|RC|RD)([A-Z]{1})?([^N]+)N/', $transaction, $trxMatch);
if ($trxMatch[2] == 'C') {
$trx[count($trx)]['credit_debit'] = static::CD_CREDIT;
} elseif ($trxMatch[2] == 'D') {
$trx[count($trx)]['credit_debit'] = static::CD_DEBIT;
} else {
throw new MT940Exception('cd mark not found in: ' . $transaction);
}
$amount = $trxMatch[4];
$amount = str_replace(',', '.', $amount);
$trx[count($trx) - 1]['amount'] = floatval($amount);
$description = $this->parseDescription($description);
$trx[count($trx) - 1]['description'] = $description;
// :61:1605110509D198,02NMSCNONREF
// 16 = year
// 0511 = valuta date
// 0509 = booking date
$year = substr($transaction, 0, 2);
$valutaDate = $this->getDate($year . substr($transaction, 2, 4));
$bookingDate = substr($transaction, 6, 4);
if (preg_match('/^\d{4}$/', $bookingDate)) {
// if valuta date is earlier than booking date, then it must be in the new year.
$year = substr($transaction, 2, 2) < substr($transaction, 6, 2) ? --$year : $year;
$bookingDate = $this->getDate($year . $bookingDate);
} else {
// if booking date not set in :61, then we have to take it from :60F
$bookingDate = $this->soaDate;
}
$trx[count($trx) - 1]['booking_date'] = $bookingDate;
$trx[count($trx) - 1]['valuta_date'] = $valutaDate;
}
}
}
return $result;
}
/**
* @param string $descr
* @return array
*/
protected function parseDescription($descr)
{
$prepared = array();
$result = array();
// prefill with empty values
for ($i = 0; $i <= 63; $i++) {
$prepared[$i] = null;
}
$descr = str_replace("\r\n", '', $descr);
$descr = str_replace('? ', '?', $descr);
preg_match_all('/\?[\r\n]*(\d{2})([^\?]+)/', $descr, $matches, PREG_SET_ORDER);
$descriptionLines = array();
$description1 = ''; // Legacy, could be removed.
$description2 = ''; // Legacy, could be removed.
foreach ($matches as $m) {
$index = (int) $m[1];
if ((20 <= $index && $index <= 29) || (60 <= $index && $index <= 63)) {
if (20 <= $index && $index <= 29) {
$description1 .= $m[2];
} else {
$description2 .= $m[2];
}
$m[2] = trim($m[2]);
if (!empty($m[2])) {
$descriptionLines[] = $m[2];
}
} else {
$prepared[$index] = $m[2];
}
}
$description = array();
if (empty($descriptionLines) || strlen($descriptionLines[0]) < 5 || $descriptionLines[0][4] !== '+') {
$description['SVWZ'] = implode('', $descriptionLines);
} else {
$lastType = null;
foreach ($descriptionLines as $line) {
if (strlen($line) > 5 && $line[4] === '+') {
if ($lastType != null) {
$description[$lastType] = trim($description[$lastType]);
}
$lastType = substr($line, 0, 4);
$description[$lastType] = substr($line, 5);
} else {
$description[$lastType] .= $line;
}
if (strlen($line) < 27) {
// Usually, lines are 27 characters long. In case characters are missing, then it's either the end
// of the current type or spaces have been trimmed from the end. We want to collapse multiple spaces
// into one and we don't want to leave trailing spaces behind. So add a single space here to make up
// for possibly missing spaces, and if it's the end of the type, it will be trimmed off later.
$description[$lastType] .= ' ';
}
}
$description[$lastType] = trim($description[$lastType]);
}
$result['description'] = $description;
$result['booking_text'] = trim($prepared[0]);
$result['primanoten_nr'] = trim($prepared[10]);
$result['description_1'] = trim($description1);
$result['bank_code'] = trim($prepared[30]);
$result['account_number'] = trim($prepared[31]);
$result['name'] = trim($prepared[32] . $prepared[33]);
$result['text_key_addition'] = trim($prepared[34]);
$result['description_2'] = trim($description2);
return $result;
}
/**
* @param string $val
* @return string
*/
protected function getDate($val)
{
$val = '20' . $val;
preg_match('/(\d{4})(\d{2})(\d{2})/', $val, $m);
return $m[1] . '-' . $m[2] . '-' . $m[3];
}
}
@@ -1,60 +0,0 @@
<?php
namespace Fhp\Response;
use Fhp\Model\Account;
/**
* Class GetAccounts
* @package Fhp\Response
*/
class GetAccounts extends Response
{
const SEG_ACCOUNT_INFORMATION = 'HIUPD';
/** @var array */
protected $accounts = array();
/**
* @return array
*/
public function getAccountsArray()
{
$accounts = $this->findSegments(static::SEG_ACCOUNT_INFORMATION);
foreach ($accounts as $account) {
$accountParts = $this->splitSegment($account);
$account = $this->createModelFromArray($accountParts);
if ($account !== null) {
$this->accounts[] = $account;
}
}
return $this->accounts;
}
/**
* Creates a Account model from array.
*
* @param array $array
* @return Account
*/
protected function createModelFromArray(array $array)
{
if (!$array[1]) {
return null;
}
$account = new Account();
list($accountNumber, $x, $countryCode, $bankCode) = explode(':', $array[1]);
$account->setId($array[1]);
$account->setAccountNumber($accountNumber);
$account->setBankCode($bankCode);
$account->setIban($array[2]);
$account->setCustomerId($array[3]);
$account->setCurrency($array[5]);
$account->setAccountOwnerName($array[6]);
$account->setAccountDescription($array[8]);
return $account;
}
}
@@ -1,56 +0,0 @@
<?php
namespace Fhp\Response;
use Fhp\Model\SEPAAccount;
/**
* Class GetSEPAAccounts
* @package Fhp\Response
*/
class GetSEPAAccounts extends Response
{
const SEG_ACCOUNT_INFORMATION = 'HISPA';
/** @var array */
protected $accounts = array();
/**
* Creates SEPA Account array list with SEPAAccount models.
*
* @return SEPAAccount[]
*/
public function getSEPAAccountsArray()
{
$accounts = $this->findSegment(static::SEG_ACCOUNT_INFORMATION);
if (is_string($accounts)) {
$accounts = $this->splitSegment($accounts);
array_shift($accounts);
foreach ($accounts as $account) {
$array = $this->splitDeg($account);
$this->accounts[] = $this->createModelFromArray($array);
}
}
return $this->accounts;
}
/**
* Creates a SEPAAccount model from array.
*
* @param array $array
* @return SEPAAccount
*/
protected function createModelFromArray(array $array)
{
$account = new SEPAAccount();
$account->setIban($array[1]);
$account->setBic($array[2]);
$account->setAccountNumber($array[3]);
$account->setSubAccount($array[4]);
$account->setBlz($array[6]);
return $account;
}
}
@@ -1,70 +0,0 @@
<?php
namespace Fhp\Response;
use Fhp\Model\Saldo;
/**
* Class GetSaldo
* @package Fhp\Response
*/
class GetSaldo extends Response
{
const SEG_ACCOUNT_INFORMATION = 'HISAL';
const SALDO_DEBIT = 'D';
const SALDO_CREDIT = 'C';
/**
* Creates a Saldo object from response body.
*
* @return Saldo|null
* @throws \Exception
*/
public function getSaldoModel()
{
$model = null;
$saldoSec = $this->findSegment(static::SEG_ACCOUNT_INFORMATION);
if (is_string($saldoSec)) {
$saldoSec = $this->splitSegment($saldoSec);
array_shift($saldoSec); // get rid of header
$model = $this->createModelFromArray($saldoSec);
}
return $model;
}
/**
* Creates a Saldo model from array.
*
* @param array $array
* @return Saldo
* @throws \Exception
*/
protected function createModelFromArray(array $array)
{
$model = new Saldo();
$saldoDeg = $this->splitDeg($array[3]);
$amount = str_replace(',', '.', $saldoDeg[1]);
$creditDebit = trim($saldoDeg[0]);
if (static::SALDO_DEBIT == $creditDebit) {
$amount = - (float) $amount;
} elseif (static::SALDO_CREDIT == $creditDebit) {
$amount = (float) $amount;
} else {
throw new \Exception('Invalid Soll-Haben-Kennzeichen: ' . $creditDebit);
}
$model->setAmount($amount);
$model->setCurrency($saldoDeg[2]);
$valutaDate = $saldoDeg[3];
preg_match('/(\d{4})(\d{2})(\d{2})/', $valutaDate, $m);
$valutaDate = new \DateTime($m[1] . '-' . $m[2] . '-' . $m[3]);
$model->setValuta($valutaDate);
return $model;
}
}
@@ -1,102 +0,0 @@
<?php
namespace Fhp\Response;
use Fhp\Model\StatementOfAccount\Statement;
use Fhp\Model\StatementOfAccount\StatementOfAccount;
use Fhp\Model\StatementOfAccount\Transaction;
use Fhp\Parser\MT940;
/**
* Class GetStatementOfAccount
* @package Fhp\Response
*/
class GetStatementOfAccount extends Response
{
const SEG_ACCOUNT_INFORMATION = 'HIKAZ';
/**
* Gets the raw MT940 string from response.
*
* @return string
*/
public function getRawMt940()
{
$seg = $this->findSegment(static::SEG_ACCOUNT_INFORMATION);
if (is_string($seg)) {
if (preg_match('/@(\d+)@(.+)/ms', $seg, $m)) {
return $m[2];
}
}
return '';
}
/**
* Creates StatementOfAccount object from raw MT940 string.
*
* @param string $rawMt940
* @return StatementOfAccount
*/
public static function createModelFromRawMt940($rawMt940)
{
$parser = new MT940($rawMt940);
return static::createModelFromArray($parser->parse(MT940::TARGET_ARRAY));
}
/**
* Adds statements to an existing StatementOfAccount object.
*
* @param array $array
* @param StatementOfAccount $statementOfAccount
* @return StatementOfAccount
*/
protected static function addFromArray(array $array, StatementOfAccount $statementOfAccount)
{
foreach ($array as $date => $statement) {
if ($statementOfAccount->hasStatementForDate($date)) {
$statementModel = $statementOfAccount->getStatementForDate($date);
} else {
$statementModel = new Statement();
$statementModel->setDate(new \DateTime($date));
$statementModel->setStartBalance((float) $statement['start_balance']['amount']);
$statementModel->setCreditDebit($statement['start_balance']['credit_debit']);
$statementOfAccount->addStatement($statementModel);
}
if (isset($statement['transactions'])) {
foreach ($statement['transactions'] as $trx) {
$transaction = new Transaction();
$transaction->setBookingDate(new \DateTime($trx['booking_date']));
$transaction->setValutaDate(new \DateTime($trx['valuta_date']));
$transaction->setCreditDebit($trx['credit_debit']);
$transaction->setAmount($trx['amount']);
$transaction->setBookingText($trx['description']['booking_text']);
$transaction->setDescription1($trx['description']['description_1']);
$transaction->setDescription2($trx['description']['description_2']);
$transaction->setStructuredDescription($trx['description']['description']);
$transaction->setBankCode($trx['description']['bank_code']);
$transaction->setAccountNumber($trx['description']['account_number']);
$transaction->setName($trx['description']['name']);
$statementModel->addTransaction($transaction);
}
}
}
return $statementOfAccount;
}
/**
* Creates a StatementOfAccount model from array.
*
* @param array $array
* @return StatementOfAccount
*/
protected static function createModelFromArray(array $array)
{
$soa = static::addFromArray($array, new StatementOfAccount());
return $soa;
}
}
@@ -1,12 +0,0 @@
<?php
namespace Fhp\Response;
/**
* Class Initialization
* @package Fhp\Response
*/
class Initialization extends Response
{
}
@@ -1,377 +0,0 @@
<?php
namespace Fhp\Response;
use Fhp\Message\AbstractMessage;
use Fhp\Segment\AbstractSegment;
use Fhp\Segment\NameMapping;
/**
* Class Response
*
* @package Fhp\Response
*/
class Response
{
/** @var string */
public $rawResponse;
/** @var string */
protected $response;
/** @var array */
protected $segments = array();
/** @var string */
protected $dialogId;
/** @var string */
protected $systemId;
/**
* Response constructor.
*
* @param string $rawResponse
*/
public function __construct($rawResponse)
{
if ($rawResponse instanceof Initialization) {
$rawResponse = $rawResponse->rawResponse;
}
$this->rawResponse = $rawResponse;
$this->response = $this->unwrapEncryptedMsg($rawResponse);
$this->segments = preg_split("#'(?=[A-Z]{4,}:\d|')#", $rawResponse);
}
/**
* Extracts dialog ID from response.
*
* @return string|null
* @throws \Exception
*/
public function getDialogId()
{
$segment = $this->findSegment('HNHBK');
if (null === $segment) {
throw new \Exception('Could not find element HNHBK. Invalid response?');
}
return $this->getSegmentIndex(4, $segment);
}
/**
* Extracts bank name from response.
*
* @return string|null
*/
public function getBankName()
{
$bankName = null;
$segment = $this->findSegment('HIBPA');
if (null != $segment) {
$split = $this->splitSegment($segment);
if (isset($split[3])) {
$bankName = $split[3];
}
}
return $bankName;
}
/**
* Some kind of HBCI pagination.
*
* @param AbstractMessage $message
*
* @return array
*/
public function getTouchDowns(AbstractMessage $message)
{
$touchdown = array();
$messageSegments = $message->getEncryptedSegments();
/** @var AbstractSegment $msgSeg */
foreach ($messageSegments as $msgSeg) {
$segment = $this->findSegmentForReference('HIRMS', $msgSeg);
if (null != $segment) {
$parts = $this->splitSegment($segment);
// remove header
array_shift($parts);
foreach ($parts as $p) {
$pSplit = $this->splitDeg($p);
if ($pSplit[0] == 3040) {
$td = $pSplit[3];
$touchdown[$msgSeg->getName()] = $td;
}
}
}
}
return $touchdown;
}
/**
* Extracts supported TAN mechanisms from response.
*
* @return array
*/
public function getSupportedTanMechanisms()
{
$segments = $this->findSegments('HIRMS');
// @todo create method to get reference element from request
foreach ($segments as $segment) {
$segment = $this->splitSegment($segment);
array_shift($segment);
foreach ($segment as $seg) {
list($id, $msg) = explode('::', $seg, 2);
if ("3920" == $id) {
if (preg_match_all('/\d{3}/', $msg, $matches)) {
return $matches[0];
}
}
}
}
return array();
}
/**
* @return int
*/
public function getHksalMaxVersion()
{
return $this->getSegmentMaxVersion('HISALS');
}
/**
* @return int
*/
public function getHkkazMaxVersion()
{
return $this->getSegmentMaxVersion('HIKAZS');
}
/**
* Checks if request / response was successful.
*
* @return bool
*/
public function isSuccess()
{
$summary = $this->getMessageSummary();
foreach ($summary as $code => $message) {
if ("9" == substr($code, 0, 1)) {
return false;
}
}
return true;
}
/**
* @return array
* @throws \Exception
*/
public function getMessageSummary()
{
return $this->getSummaryBySegment('HIRMG');
}
/**
* @return array
* @throws \Exception
*/
public function getSegmentSummary()
{
return $this->getSummaryBySegment('HIRMS');
}
/**
* @param string $name
*
* @return array
* @throws \Exception
*/
protected function getSummaryBySegment($name)
{
if (!in_array($name, array('HIRMS', 'HIRMG'))) {
throw new \Exception('Invalid segment for message summary. Only HIRMS and HIRMG supported');
}
$result = array();
$segment = $this->findSegment($name);
$segment = $this->splitSegment($segment);
array_shift($segment);
foreach ($segment as $de) {
$de = $this->splitDeg($de);
$result[$de[0]] = $de[2];
}
return $result;
}
/**
* @param string $segmentName
*
* @return int
*/
public function getSegmentMaxVersion($segmentName)
{
$version = 3;
$segments = $this->findSegments($segmentName);
foreach ($segments as $s) {
$parts = $this->splitSegment($s);
$segmentHeader = $this->splitDeg($parts[0]);
$curVersion = (int) $segmentHeader[2];
if ($curVersion > $version) {
$version = $curVersion;
}
}
return $version;
}
/**
* @return string
* @throws \Exception
*/
public function getSystemId()
{
$segment = $this->findSegment('HISYN');
if (!preg_match('/HISYN:\d+:\d+:\d+\+(.+)/', $segment, $matches)) {
throw new \Exception('Could not determine system id.');
}
return $matches[1];
}
/**
* @param bool $translateCodes
*
* @return string
*/
public function humanReadable($translateCodes = false)
{
return str_replace(
array("'", '+'),
array(PHP_EOL, PHP_EOL . " "),
$translateCodes
? NameMapping::translateResponse($this->rawResponse)
: $this->rawResponse
);
}
/**
* @param string $name
* @param AbstractSegment $reference
*
* @return string|null
*/
protected function findSegmentForReference($name, AbstractSegment $reference)
{
$segments = $this->findSegments($name);
foreach ($segments as $seg) {
$segSplit = $this->splitSegment($seg);
$segSplit = array_shift($segSplit);
$segSplit = $this->splitDeg($segSplit);
if ($segSplit[3] == $reference->getSegmentNumber()) {
return $seg;
}
}
return null;
}
/**
* @param string $name
*
* @return string|null
*/
protected function findSegment($name)
{
return $this->findSegments($name, true);
}
/**
* @param string $name
* @param bool $one
*
* @return array|null|string
*/
protected function findSegments($name, $one = false)
{
$found = $one ? null : array();
foreach ($this->segments as $segment) {
$split = explode(':', $segment, 2);
if ($split[0] == $name) {
if ($one) {
return $segment;
}
$found[] = $segment;
}
}
return $found;
}
/**
* @param $segment
*
* @return array
*/
protected function splitSegment($segment)
{
$parts = preg_split('/\+(?<!\?\+)/', $segment);
foreach ($parts as &$part) {
$part = str_replace('?+', '+', $part);
}
return $parts;
}
/**
* @param $deg
*
* @return array
*/
protected function splitDeg($deg)
{
return explode(':', $deg);
}
/**
* @param int $idx
* @param $segment
*
* @return string|null
*/
protected function getSegmentIndex($idx, $segment)
{
$segment = $this->splitSegment($segment);
if (isset($segment[$idx - 1])) {
return $segment[$idx - 1];
}
return null;
}
/**
* @param string $response
*
* @return string
*/
protected function unwrapEncryptedMsg($response)
{
if (preg_match('/HNVSD:\d+:\d+\+@\d+@(.+)\'\'/', $response, $matches)) {
return $matches[1];
}
return $response;
}
}
@@ -1,108 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Abstract Class AbstractSegment.
*
* @package Fhp\Segment
*/
abstract class AbstractSegment implements SegmentInterface
{
const SEGMENT_SEPARATOR = "'";
const DEFAULT_COUNTRY_CODE = 280;
/** @var string */
protected $type;
/** @var int */
protected $segmentNumber;
/** @var int */
protected $version;
/** @var array */
protected $dataElements;
/**
* AbstractSegment constructor.
*
* @param $type
* @param $segmentNumber
* @param $version
* @param array $dataElements
*/
public function __construct($type, $segmentNumber, $version, array $dataElements = array())
{
$this->type = strtoupper($type);
$this->version = $version;
$this->segmentNumber = $segmentNumber;
$this->dataElements = $dataElements;
}
/**
* @param array $dataElements
*/
public function setDataElements(array $dataElements = array())
{
$this->dataElements = $dataElements;
}
/**
* @return array
*/
public function getDataElements()
{
return $this->dataElements;
}
/**
* @return string
*/
public function toString()
{
$string = $this->type . ':' . $this->segmentNumber . ':' . $this->version;
foreach ($this->dataElements as $de) {
$string .= '+' . (string) $de;
}
return $string . static::SEGMENT_SEPARATOR;
}
/**
* @return string
*/
public function __toString()
{
return $this->toString();
}
/**
* @param bool $translateCodes
* @return string
*/
public function humanReadable($translateCodes = false)
{
return str_replace(
array("'", '+'),
array(PHP_EOL, PHP_EOL . " "),
$translateCodes
? NameMapping::translateResponse($this->toString())
: $this->toString()
);
}
/**
* @return int
*/
public function getSegmentNumber()
{
return $this->segmentNumber;
}
/**
* @return int
*/
public function getVersion()
{
return $this->version;
}
}
@@ -1,41 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class HKEND (Dialogende)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
* Section: C.4.1.2
*
* @package Fhp\Segment
*/
class HKEND extends AbstractSegment
{
const NAME = 'HKEND';
const VERSION = 1;
/**
* HKEND constructor.
* @param $segmentNumber
* @param $dialogId
*/
public function __construct($segmentNumber, $dialogId)
{
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array($dialogId)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,51 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataTypes\Kik;
/**
* Class HKIDN (Identifikation)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
* Section: C.3.1.2
*
* @package Fhp\Segment
*/
class HKIDN extends AbstractSegment
{
const NAME = 'HKIDN';
const VERSION = 2;
const COUNTRY_CODE = 280; // Germany
/**
* HKIDN constructor.
* @param int $segmentNumber
* @param string $bankCode
* @param string $userName
* @param int $systemId
*/
public function __construct($segmentNumber, $bankCode, $userName, $systemId = 0)
{
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array(
new Kik(static::COUNTRY_CODE, $bankCode),
$userName,
$systemId,
1 // Kunden-ID
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,63 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataTypes\Dat;
/**
* Class HKKAZ (Kontoumsätze anfordern/Zeitraum)
* Segment type: Geschäftsvorfall
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Messages_Geschaeftsvorfaelle_2015-08-07_final_version.pdf
* Section: C.2.1.1.1.2
*
* @package Fhp\Segment
*/
class HKKAZ extends AbstractSegment
{
const NAME = 'HKKAZ';
const ALL_ACCOUNTS_N = 'N';
const ALL_ACCOUNTS_Y = 'J';
/**
* HKKAZ constructor.
* @param int $version
* @param int $segmentNumber
* @param mixed $ktv
* @param array $allAccounts
* @param \DateTime $from
* @param \DateTime $to
* @param string|null $touchdown
*/
public function __construct(
$version,
$segmentNumber,
$ktv,
$allAccounts,
\DateTime $from,
\DateTime $to,
$touchdown = null
) {
parent::__construct(
static::NAME,
$segmentNumber,
$version,
array(
$ktv,
$allAccounts,
new Dat($from),
new Dat($to),
null,
$touchdown
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,48 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class HKSAL (Saldenabfrage)
* Segment type: Geschäftsvorfall
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Messages_Geschaeftsvorfaelle_2015-08-07_final_version.pdf
* Section: C.2.1.2
*
* @package Fhp\Segment
*/
class HKSAL extends AbstractSegment
{
const NAME = 'HKSAL';
const VERSION = 7;
const ALL_ACCOUNTS_N = 'N';
const ALL_ACCOUNTS_Y = 'J';
/**
* HKSAL constructor.
* @param int $version
* @param int $segmentNumber
* @param mixed $ktv
* @param array $allAccounts
*/
public function __construct($version, $segmentNumber, $ktv, $allAccounts)
{
parent::__construct(
static::NAME,
$segmentNumber,
$version,
array(
$ktv,
$allAccounts,
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,43 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataTypes\Ktv;
/**
* Class HKSPA (SEPA-Kontoverbindung anfordern)
* Segment type: Geschäftsvorfall
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Messages_Geschaeftsvorfaelle_2015-08-07_final_version.pdf
* Section: C.10.1.3
*
* @package Fhp\Segment
*/
class HKSPA extends AbstractSegment
{
const NAME = 'HKSPA';
const VERSION = 1;
/**
* HKSPA constructor.
* @param int $segmentNumber
* @param Ktv|null $ktv
*/
public function __construct($segmentNumber, Ktv $ktv = null)
{
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array($ktv)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,47 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class HKSYN (Synchronisation)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
* Section: C.8.1.2
*
* @package Fhp\Segment
*/
class HKSYN extends AbstractSegment
{
const NAME = 'HKSYN';
const VERSION = 3;
const SYNC_MODE_NEW_CUSTOMER_ID = 0; // Neue Kundensystem-ID zurückmelden
const SYNC_MODE_LAST_MSG_NUMBER = 1; // Letzte verarbeitete Nachrichtennummer zurückmelden
const SYNC_MODE_SIGNATURE_ID = 2; // Signatur-ID zurückmelden
/**
* HKSYN constructor.
* @param int $segmentNumber
* @param int $syncMode
*/
public function __construct(
$segmentNumber,
$syncMode = self::SYNC_MODE_NEW_CUSTOMER_ID
) {
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array($syncMode)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,68 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class HKVVB (Verarbeitungsvorbereitung)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
* Section: C.3.1.3
*
* @package Fhp\Segment
*/
class HKVVB extends AbstractSegment
{
const NAME = 'HKVVB';
const VERSION = 3;
const DEFAULT_BPD_VERSION = 0;
const DEFAULT_UPD_VERSION = 0;
const LANG_DEFAULT = 0;
const LANG_DE = 1;
const LANG_EN = 2;
const LANG_FR = 3;
const DEFAULT_PRODUCT_NAME = 'fints-hbci-php';
const DEFAULT_PRODUCT_VERSION = '1.0';
/**
* HKVVB constructor.
* @param int $segmentNumber
* @param int $bpdVersion
* @param int $updVersion
* @param int $dialogLanguage
* @param string $productName
* @param string $productVersion
*/
public function __construct(
$segmentNumber,
$bpdVersion = self::DEFAULT_BPD_VERSION,
$updVersion = self::DEFAULT_UPD_VERSION,
$dialogLanguage = self::LANG_DEFAULT,
$productName = self::DEFAULT_PRODUCT_NAME,
$productVersion = self::DEFAULT_PRODUCT_VERSION
) {
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array(
$bpdVersion,
$updVersion,
$dialogLanguage,
$productName,
$productVersion
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,52 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class HNHBK (Nachrichtenkopf)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
* Section: B.5.2
*
* @package Fhp\Segment
*/
class HNHBK extends AbstractSegment
{
const NAME = 'HNHBK';
const VERSION = 3;
const HEADER_LENGTH = 29;
/**
* HNHBK constructor.
* @param string $messageLength
* @param string $dialogId
* @param int $messageNumber
*/
public function __construct($messageLength, $dialogId, $messageNumber)
{
if (strlen($messageLength) != 12) {
$messageLength = str_pad((int) $messageLength + static::HEADER_LENGTH + strlen($dialogId) + strlen($messageNumber), 12, '0', STR_PAD_LEFT);
}
parent::__construct(
static::NAME,
1, // always the first segment
static::VERSION,
array(
$messageLength,
300, // HBCI / FINTS version 3.0,
$dialogId,
$messageNumber,
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,45 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataTypes\Kik;
/**
* Class HNHBS (Nachrichtenabschluss)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
* Section: B.5.3
*
* @package Fhp\Segment
*/
class HNHBS extends AbstractSegment
{
const NAME = 'HNHBS';
const VERSION = 1;
/**
* HNHBS constructor.
* @param int $segmentNumber
* @param int $messageNumber
*/
public function __construct(
$segmentNumber,
$messageNumber
) {
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array($messageNumber)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,51 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataTypes\Kik;
/**
* Class HNSHA (Signaturabschluss)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Security_Sicherheitsverfahren_HBCI_Rel_20130718_final_version.pdf
* Section: B.5.2
*
* @package Fhp\Segment
*/
class HNSHA extends AbstractSegment
{
const NAME = 'HNSHA';
const VERSION = 2;
/**
* HNSHA constructor.
* @param int $segmentNumber
* @param string $securityControlReference
* @param string $pin
*/
public function __construct(
$segmentNumber,
$securityControlReference,
$pin
) {
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array(
$securityControlReference,
'',
$pin
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,90 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataElementGroups\HashAlgorithm;
use Fhp\DataElementGroups\KeyName;
use Fhp\DataElementGroups\SecurityDateTime;
use Fhp\DataElementGroups\SecurityIdentificationDetails;
use Fhp\DataElementGroups\SecurityProfile;
use Fhp\DataElementGroups\SignatureAlgorithm;
/**
* Class HNSHK (Signaturkopf)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Security_Sicherheitsverfahren_HBCI_Rel_20130718_final_version.pdf
* Section: B.5.1
*
* @package Fhp\Segment
*/
class HNSHK extends AbstractSegment
{
const NAME = 'HNSHK';
const VERSION = 4;
const SECURITY_FUNC_NRO = 1; // Non-Repudiation of Origin, für RAH, RDH (NRO)
const SECURITY_FUNC_AUT = 2; // Message Origin Authentication, für RAH, RDH und DDV (AUT)
const SECURITY_FUNC_ENC = 4; // Encryption, Verschlüsselung und evtl. Komprimierung (ENC)
const SECURITY_FUNC_999 = 999;
const SECURITY_BOUNDARY_SHM = 1; // Signaturkopf und HBCI-Nutzdaten (SHM)
const SECURITY_BOUNDARY_SHT = 2; // Von Signaturkopf bis Signaturabschluss (SHT)
const SECURITY_SUPPLIER_ROLE_ISS = 1; // Der Unterzeichner ist Herausgeber der signierten Nachricht, z.B. Erfasser oder Erstsignatur (ISS)
const SECURITY_SUPPLIER_ROLE_CON = 3; // Der Unterzeichner unterstützt den Inhalt der Nachricht, z.B. bei Zweitsignatur (CON)
const SECURITY_SUPPLIER_ROLE_WIT = 4; // Der Unterzeichner ist Zeuge, aber für den Inhalt der Nachricht nicht verantwortlich, z.B. Übermittler, welcher nicht Erfasser ist (WIT)
/**
* HNSHK constructor.
* @param int $segmentNumber
* @param string $securityReference
* @param string $countryCode
* @param string $bankCode
* @param string $userName
* @param int $systemId
* @param int $securityFunction
* @param int $securityBoundary
* @param int $securitySupplierRole
* @param int $pinTanVersion
*/
public function __construct(
$segmentNumber,
$securityReference,
$countryCode,
$bankCode,
$userName,
$systemId = 0,
$securityFunction = self::SECURITY_FUNC_999,
$securityBoundary = self::SECURITY_BOUNDARY_SHM,
$securitySupplierRole = self::SECURITY_SUPPLIER_ROLE_ISS,
$pinTanVersion = SecurityProfile::PROFILE_VERSION_1
) {
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array(
new SecurityProfile(SecurityProfile::PROFILE_PIN, $pinTanVersion), #2
$securityFunction, #3
$securityReference, #4
$securityBoundary, #5
$securitySupplierRole, #6
new SecurityIdentificationDetails(SecurityIdentificationDetails::CID_NONE, $systemId), #7
1, #8
new SecurityDateTime(), #9
new HashAlgorithm(), #10
new SignatureAlgorithm(), #11
new KeyName($countryCode, $bankCode, $userName, KeyName::KEY_TYPE_SIGNATURE) #12
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,61 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataTypes\Bin;
/**
* Class HNVSD (Verschlüsselte Daten)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Security_Sicherheitsverfahren_HBCI_Rel_20130718_final_version.pdf
* Section: B.5.4
*
* @package Fhp\Segment
*/
class HNVSD extends AbstractSegment
{
const NAME = 'HNVSD';
const VERSION = 1;
/**
* HNVSD constructor.
* @param int $segmentNumber
* @param string $encodedData
*/
public function __construct($segmentNumber, $encodedData)
{
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array(new Bin($encodedData))
);
}
/**
* @return Bin
*/
public function getEncodedData()
{
$des = $this->getDataElements();
return $des[0];
}
/**
* @param string $data
*/
public function setEncodedData($data)
{
$this->setDataElements(array(new Bin($data)));
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,84 +0,0 @@
<?php
namespace Fhp\Segment;
use Fhp\DataElementGroups\EncryptionAlgorithm;
use Fhp\DataElementGroups\KeyName;
use Fhp\DataElementGroups\SecurityDateTime;
use Fhp\DataElementGroups\SecurityIdentificationDetails;
use Fhp\DataElementGroups\SecurityProfile;
/**
* Class HNVSK (Verschlüsselungskopf)
* Segment type: Administration
*
* @link: http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Security_Sicherheitsverfahren_HBCI_Rel_20130718_final_version.pdf
* Section: B.5.3
*
* @package Fhp\Segment
*/
class HNVSK extends AbstractSegment
{
const NAME = 'HNVSK';
const VERSION = 3;
const SECURITY_SUPPLIER_ROLE_ISS = 1;
const SECURITY_SUPPLIER_ROLE_CON = 3;
const SECURITY_SUPPLIER_ROLE_WIT = 4;
const COMPRESSION_NONE = 0;
const COMPRESSION_LZW = 1;
const COMPRESSION_COM = 2;
const COMPRESSION_LZSS = 3;
const COMPRESSION_LZHUFF = 4;
const COMPRESSION_ZIP = 5;
const COMPRESSION_GZIP = 6;
const COMPRESSION_BZIP2 = 7;
const COMPRESSION_NEGOTIATE = 999;
/**
* HNVSK constructor.
* @param int $segmentNumber
* @param string $bankCode
* @param string $userName
* @param int $systemId
* @param int $securitySupplierRole
* @param int $countryCode
* @param int $compression
* @param int $pinTanVersion
*/
public function __construct(
$segmentNumber,
$bankCode,
$userName,
$systemId = 0,
$securitySupplierRole = self::SECURITY_SUPPLIER_ROLE_ISS,
$countryCode = self::DEFAULT_COUNTRY_CODE,
$compression = self::COMPRESSION_NONE,
$pinTanVersion = SecurityProfile::PROFILE_VERSION_1
) {
parent::__construct(
static::NAME,
$segmentNumber,
static::VERSION,
array(
new SecurityProfile(SecurityProfile::PROFILE_PIN, $pinTanVersion),
998, // Just informational / invalid for PIN/TAN,
$securitySupplierRole,
new SecurityIdentificationDetails(SecurityIdentificationDetails::CID_NONE, $systemId),
new SecurityDateTime(),
new EncryptionAlgorithm(),
new KeyName($countryCode, $bankCode, $userName),
$compression,
)
);
}
/**
* @return string
*/
public function getName()
{
return static::NAME;
}
}
@@ -1,119 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class NameMapping
* @package Fhp\Segment
*/
class NameMapping
{
protected static $mapping = array(
// Formals
// http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Formals_2011-06-14_final_version.pdf
// Section: H.1.3
'HKEND' => 'Dialogende',
'HKIDN' => 'Identifikation',
'HKSYN' => 'Synchronisation',
'HKVVB' => 'Verarbeitungsvorbereitung',
'HNHBK' => 'Nachrichtenkopf',
'HNHBS' => 'Nachrichtenabschluss',
'HNSHA' => 'Signaturabschluss',
'HNSHK' => 'Signaturkopf',
'HNVSD' => 'Verschlüsselte Daten',
'HNVSK' => 'Verschlüsselungskopf',
'HKISA' => 'Anforderung eines öffentlichen Schlüssels',
'HIBPA' => 'Bankparameter allgemein',
'HISSP' => 'Bestätigung der Schlüsselsperrung',
'HIKPV' => 'Komprimierungsverfahren',
'HIUPD' => 'Kontoinformation',
'HIKIM' => 'Kreditinstitutsmeldung',
'HKLIF' => 'Life-Indikator',
'HIRMS' => 'Rückmeldung zu Segmenten',
'HIRMG' => 'Rückmeldungen zur Gesamtnachricht',
'HKSAK' => 'Schlüsseländerung',
'HKSSP' => 'Schlüsselsperrung',
'HISHV' => 'Sicherheitsverfahren',
'HISYN' => 'Synchronisierungsantwort',
'HIISA' => 'Übermittlung eines öffentlichen Schlüssels',
'HIUPA' => 'Userparameter allgemein',
'HIKOM' => 'Kommunikationszugang rückmelden',
// Geschäftsvorfälle
// http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Messages_Geschaeftsvorfaelle_2015-08-07_final_version.pdf
// Section: E.1
'HKADR' => 'Adressänderung',
'HIADRS' => 'Adressänderung Parameter',
'HITEA' => 'Änderung terminierter Einzellastschrift bestätigen',
'HIDSA' => 'Änderung terminierter SEPA-Einzellastschriften bestätigen',
'HIBSA' => 'Änderung terminierter SEPA-Firmeneinzellastschrift bestätigen',
'HICSA' => 'Änderung terminierter SEPA-Überweisung bestätigen',
'HITUA' => 'Änderung terminierter Überweisung bestätigen',
'HICVE' => 'Anlage vorbereiteter SEPA-Überweisung bestätigen',
'HIVUE' => 'Anlage vorbereiteter Überweisung bestätigen',
'HKCTD' => 'Auftragsdetails für C-Transaktionen',
'HICTDS' => 'Auftragsdetails für C-Transaktionen Parameter',
'HICTD' => 'Auftragsdetails für C-Transaktionen rückmelden',
'HKAUE' => 'Ausgeführte Überweisungen anfordern',
'HIAUE' => 'Ausgeführte Überweisungen rückmelden',
'HIAUES' => 'Ausgeführte Überweisungen Parameter',
'HKAUB' => 'Auslandsüberweisung',
'HKAOM' => 'Auslandsüberweisung ohne Meldeteil',
'HIAOMS' => 'Auslandsüberweisung ohne Meldeteil Parameter',
'HIAUBS' => 'Auslandsüberweisung Parameter',
'HKCTA' => 'Auslösen von C-Transaktionen',
'HICTAS' => 'Auslösen von C-Transaktionen Parameter',
'HIAPN' => 'Auswahl Postfach-Nachrichtentypen rückmelden',
'HKFDB' => 'Bearbeitungsstatus Dokument anfordern ',
'HIFDBS' => 'Bearbeitungsstatus Dokument Parameter',
'HIFDB' => 'Bearbeitungsstatus Dokument rückmelden',
'HKPPB' => 'Bestand Daueraufträge Prepaidkarte laden anfordern',
'HIPPBS' => 'Bestand Daueraufträge Prepaidkarte laden Parameter',
'HIPPB' => 'Bestand Daueraufträge Prepaidkarte laden rückmelden',
'HKCUB' => 'Bestand Empfängerkonten anfordern',
'HKLWB' => 'Bestand Lastschriftwiderspruch',
'HKSAL' => 'Saldenabfrage',
'HISALS' => 'Saldenabfrage Parameter',
'HISAL' => 'Saldenrückmeldung',
'HIEKAS' => 'Kontoauszug Parameter',
'HIKAZS' => 'Kontoumsätze/Zeitraum Parameter',
'HIQTGS' => 'Empfangsquittung Parameter',
'HICSBS' => 'Bestand terminierter SEPA-Überweisungen Parameter',
'HICSLS' => 'Terminierte SEPA-Überweisung löschen Parameter',
'HKSPA' => 'SEPA-Kontoverbindung anfordern',
// tbc
// PIN/TAN
// http://www.hbci-zka.de/dokumente/spezifikation_deutsch/fintsv3/FinTS_3.0_Security_Sicherheitsverfahren_PINTAN_Rel_20101027_final_version.pdf
//
'HIPAES' => 'PIN ändern Parameter',
'HIPSPS' => 'PIN sperren Parameter',
);
/**
* @param string $code
* @return string
*/
public static function codeToName($code)
{
return isset(static::$mapping[$code]) ? static::$mapping[$code] : $code;
}
/**
* @param string $name
* @return string
*/
public static function nameToCode($name)
{
$flipped = array_flip(static::$mapping);
return isset($flipped[$name]) ? $flipped[$name] : $name;
}
/**
* @param string $text
* @return string
*/
public static function translateResponse($text)
{
return str_replace(array_flip(static::$mapping), static::$mapping, $text);
}
}
@@ -1,35 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Class Segment
* @package Fhp\Segment
*/
class Segment extends AbstractSegment
{
/**
* @param string $string
* @return Segment
*/
public static function createFromString($string)
{
$lines = explode('+', $string);
$header = array_shift($lines);
$headerParts = explode(':', $header);
$name = strtoupper($headerParts[0]);
$segmentNumber = $headerParts[1];
$version = $headerParts[2];
return new self($name, 0, $segmentNumber, $version, $lines);
}
/**
* @return string
*/
public function getName()
{
return $this->type;
}
}
@@ -1,24 +0,0 @@
<?php
namespace Fhp\Segment;
/**
* Interface SegmentInterface
* @package Fhp\Segment
*/
interface SegmentInterface
{
/**
* Returns string representation of object.
*
* @return string
*/
public function __toString();
/**
* Gets the name of the segment.
*
* @return string
*/
public function getName();
}
@@ -1,47 +0,0 @@
<?php
namespace Tests\Fhp;
use Fhp\Adapter\AdapterInterface;
use Fhp\Adapter\Curl;
use Fhp\Connection;
use Fhp\Message\Message;
class ConnectionTest extends \PHPUnit_Framework_TestCase
{
/** @var \PHPUnit_Framework_MockObject_MockObject|AdapterInterface */
protected $adapter;
/** @var \PHPUnit_Framework_MockObject_MockObject|Message */
protected $message;
public function setUp()
{
$this->adapter = $this->getMockBuilder('\Fhp\Adapter\Curl')
->disableOriginalConstructor()
->setMethods(array('send'))
->getMock();
$this->message = $this->getMockBuilder('\Fhp\Message\Message')
->disableOriginalConstructor()
->getMock();
}
public function test_can_set_and_get_adapter()
{
$conn = new Connection($this->adapter);
$this->assertEquals($this->adapter, $conn->getAdapter());
}
public function test_send_calls_adapter_send()
{
$this->adapter->expects($this->once())
->method('send')
->with($this->message)
->will($this->returnValue('response text'));
$conn = new Connection($this->adapter);
$res = $conn->send($this->message);
$this->assertInternalType('string', $res);
}
}

Some files were not shown because too many files have changed in this diff Show More