| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/seaside.pacim.de/web/ |
Upload File : |
<?php
/**
* booking-parking.php – Stellplatz einer Buchung wechseln (Halle 1 <-> Außen 2)
* inkl. Live-Preisvorschau. Session-/Admin-geschützt.
*
* GET action=info&invoice_id= -> { ok, current, vehicles, halle:{net,gross}, aussen:{net,gross}, types:{1,2} }
* POST action=save&invoice_id=&type=(1|2) -> { ok, type }
*
* Preis = NETTO-Parkplatzpreis je Fahrzeug (pacim_parking_prices, Typ × Dauer × Jahr) wie bei der
* Buchungsanlage; aktualisiert booking_type ALLER Buchungen der Rechnung und deren Parkplatz-
* Position (product_id 1/2, Titel, Netto-Preis). Gesamtsumme (full_price) wird live aus den
* Positionen berechnet -> Buchungsansicht muss nur neu geladen werden.
*/
require_once( __DIR__ . '/includes/config.inc.php' );
@ini_set( 'display_errors', '0' );
error_reporting( 0 );
ob_start();
function bp_json( $a ) { while ( ob_get_level() > 0 ) ob_end_clean(); header( 'Content-Type: application/json; charset=utf-8' ); echo json_encode( $a ); exit(); }
if ( ! function_exists( 'is_admin' ) || ! is_admin() ) { http_response_code( 403 ); bp_json( array( 'ok' => false, 'error' => 'forbidden' ) ); }
$db = new MysqliDb( MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB );
$action = $_GET['action'] ?? ( $_POST['action'] ?? '' );
/** Buchungen einer Rechnung (für Preis & Update). */
function bp_bookings( $db, $iid ) {
return $db->rawQuery( "SELECT booking_id, booking_begin, booking_end, booking_type FROM pacim_booking WHERE booking_invoice = ? ORDER BY booking_id ASC", array( (int) $iid ) );
}
/** Summe NETTO-Parkplatzpreis über alle Fahrzeuge der Rechnung für einen Typ (1/2). */
function bp_net_total( $db, $bookings, $type ) {
$net = 0.0;
foreach ( (array) $bookings as $b ) {
$dur = bookingservice::duration( $b['booking_begin'], $b['booking_end'] );
$year = (int) date( 'Y', strtotime( substr( (string) $b['booking_begin'], 0, 10 ) ) );
$n = bookingservice::parkingPriceNet( (int) $type, $dur, $year );
if ( $n === false ) $n = 0.0;
$net += (float) $n;
}
return round( $net, 2 );
}
if ( $action === 'info' ) {
$iid = (int) ( $_GET['invoice_id'] ?? 0 );
$bk = bp_bookings( $db, $iid );
if ( ! count( $bk ) ) bp_json( array( 'ok' => false, 'error' => 'Buchung nicht gefunden.' ) );
$current = (int) $bk[0]['booking_type'];
$halle = bp_net_total( $db, $bk, 1 );
$aussen = bp_net_total( $db, $bk, 2 );
bp_json( array(
'ok' => true,
'current' => $current,
'vehicles' => count( $bk ),
'types' => array( '1' => 'Halle', '2' => 'Außen' ),
'halle' => array( 'net' => $halle, 'gross' => round( $halle * 1.19, 2 ) ),
'aussen' => array( 'net' => $aussen, 'gross' => round( $aussen * 1.19, 2 ) ),
) );
}
if ( $action === 'save' ) {
if ( $_SERVER['REQUEST_METHOD'] !== 'POST' ) bp_json( array( 'ok' => false, 'error' => 'POST erforderlich.' ) );
$iid = (int) ( $_POST['invoice_id'] ?? 0 );
$type = ( (int) ( $_POST['type'] ?? 1 ) === 2 ) ? 2 : 1;
$inv = $db->rawQueryOne( "SELECT invoice_status FROM pacim_invoice WHERE invoice_id = ?", array( $iid ) );
if ( ! $inv ) bp_json( array( 'ok' => false, 'error' => 'Rechnung nicht gefunden.' ) );
if ( (int) $inv['invoice_status'] === 3 ) bp_json( array( 'ok' => false, 'error' => 'Stornierte Buchung kann nicht geändert werden.' ) );
$bk = bp_bookings( $db, $iid );
if ( ! count( $bk ) ) bp_json( array( 'ok' => false, 'error' => 'Buchung nicht gefunden.' ) );
$logBefore = apilog::snapshot( $db, (int) $bk[0]['booking_id'] ); // Vorher für Historie/Rückgängig
$pt = $db->rawQueryOne( "SELECT product_title FROM pacim_products WHERE product_id = ?", array( $type ) );
$title = ( $pt && $pt['product_title'] !== '' ) ? $pt['product_title'] : ( $type === 2 ? 'Außenparkplatz' : 'Hallenparkplatz' );
foreach ( $bk as $b ) {
$dur = bookingservice::duration( $b['booking_begin'], $b['booking_end'] );
$year = (int) date( 'Y', strtotime( substr( (string) $b['booking_begin'], 0, 10 ) ) );
$n = bookingservice::parkingPriceNet( $type, $dur, $year );
if ( $n === false ) $n = 0.0;
// Parkplatz-Position(en) dieses Fahrzeugs (product_id 1/2) auf neuen Typ/Preis setzen
$db->rawQuery(
"UPDATE pacim_invoice_pos SET product_id = ?, invoice_pos_title = ?, invoice_pos_price = ? WHERE invoice_id = ? AND booking_id = ? AND product_id IN (1,2)",
array( $type, $title, $n, $iid, (int) $b['booking_id'] )
);
}
// Fallback: Parkplatz-Positionen ohne booking_id-Zuordnung ebenfalls umstellen (Preis aus erstem Fahrzeug)
$dur0 = bookingservice::duration( $bk[0]['booking_begin'], $bk[0]['booking_end'] );
$year0 = (int) date( 'Y', strtotime( substr( (string) $bk[0]['booking_begin'], 0, 10 ) ) );
$n0 = bookingservice::parkingPriceNet( $type, $dur0, $year0 ); if ( $n0 === false ) $n0 = 0.0;
$db->rawQuery( "UPDATE pacim_invoice_pos SET product_id = ?, invoice_pos_title = ?, invoice_pos_price = ? WHERE invoice_id = ? AND (booking_id IS NULL OR booking_id = 0) AND product_id IN (1,2)", array( $type, $title, $n0, $iid ) );
// booking_type aller Buchungen der Rechnung umstellen
$db->rawQuery( "UPDATE pacim_booking SET booking_type = ? WHERE booking_invoice = ?", array( $type, $iid ) );
// Rechnungssumme (pacim_invoice.invoice_price) konsistent zu den neuen Positionen setzen.
if ( class_exists( 'bookingservice' ) ) bookingservice::recalcInvoice( $iid );
// Änderung protokollieren (für Historie-Tab + Rückgängig)
apilog::record( array(
'key_name' => trim( (string) ( $_SESSION['user_name'] ?? 'Administrator' ) ),
'ip' => $_SERVER['REMOTE_ADDR'] ?? '', 'method' => 'POST',
'resource' => 'booking', 'action' => 'parking', 'kind' => 'write',
'booking' => (int) $bk[0]['booking_id'], 'invoice' => $iid,
'target' => 'Stellplatz gewechselt auf ' . ( $type === 2 ? 'Außen' : 'Halle' ),
'changes' => apilog::diff( $logBefore, apilog::snapshot( $db, (int) $bk[0]['booking_id'] ) ),
) );
bp_json( array( 'ok' => true, 'type' => $type ) );
}
http_response_code( 400 );
bp_json( array( 'ok' => false, 'error' => 'unknown_action' ) );