diff --git a/copri4/main/js/rentalator.js b/copri4/main/js/rentalator.js new file mode 100644 index 0000000..83d6aae --- /dev/null +++ b/copri4/main/js/rentalator.js @@ -0,0 +1,84 @@ + +function rental_request(url,bikeID,bookingID) { + console.log('getURL: ' + url); + console.log('bike: ' + bikeID); + console.log('pos_id: ' + bookingID); + if(bookingID){ + bikeID = bookingID; + console.log('Take bikeID from requesting bookinID: ' + bikeID); + } + const button_reserv = document.querySelector('#button_reserv_' + bikeID); + const button_cancel = document.querySelector('#button_cancel_' + bikeID); + const return_state = document.querySelector('#return_state_' + bikeID); + const reserved_bikes = document.querySelector('#reserved_bikes'); + + $.getJSON( url, function( data ) { + console.log('state=' + data.shareejson.state + '|bike: ' + data.shareejson.bike + '==' + bikeID + '| bookingID: ' + data.shareejson.pos_id + '==' + bookingID); + + var DID = data.shareejson.bike; + if(data.shareejson.pos_id && bookingID){ + DID = data.shareejson.pos_id; + console.log('Take DID from responsing pos_id: ' + DID); + } + + if(data.shareejson.response_state.match(/Failure/)){ + return_state.style = 'color:red'; + } + + if(data.shareejson.state == 'requested' && DID == bikeID){ + return_state.textContent = data.shareejson.response_text; + button_reserv.style.display = 'none'; + button_cancel.style.display = 'block'; + } + else if(data.shareejson.state == 'reserved' && DID == bikeID){ + return_state.textContent = data.shareejson.response_text; + button_reserv.style.display = 'none'; + button_cancel.style.display = 'block'; + } + else if(data.shareejson.state == 'available' && DID == bikeID){ + return_state.textContent = data.shareejson.response_text; + button_cancel.style.display = 'none'; + button_reserv.style.display = 'block'; + } + else { + return_state.style = 'color:red'; + return_state.textContent = data.shareejson.response_text; + } + + if(1 == 2){ + for (const key in data.shareejson.bikes_occupied) { + console.log(key + ':' + data.shareejson.bikes_occupied[key].bike); + reserved_bikes.textContent = data.shareejson.bikes_occupied[key].bike; + } + } + + }); +} +var acc = document.getElementsByClassName("accordion"); +var i; + +for (i = 0; i < acc.length; i++) { + acc[i].addEventListener("click", function() { + this.classList.toggle("active"); + var panel = this.nextElementSibling; + if (panel.style.maxHeight) { + panel.style.maxHeight = null; + } else { + panel.style.maxHeight = panel.scrollHeight + "px"; + } + }); +} + +var scrollToTopBtn = document.getElementById("scroll-top-wrapper"); +var rootElement = document.documentElement; + +function scrollToTop() { + // Scroll to top logic + rootElement.scrollTo({ + top: 0, + behavior: "smooth" + }); +} +scrollToTopBtn.addEventListener("click", scrollToTop); + + diff --git a/copri4/main/src/Mod/APIfunc.pm b/copri4/main/src/Mod/APIfunc.pm index 5dfd8dc..657759b 100755 --- a/copri4/main/src/Mod/APIfunc.pm +++ b/copri4/main/src/Mod/APIfunc.pm @@ -17,6 +17,7 @@ use Digest::MD5 qw(md5 md5_hex); use Digest::SHA qw(sha256_base64); use Scalar::Util qw(looks_like_number); use DateTime; +use DateTime::Format::Strptime; use DateTime::Format::Pg; use URI::Encode; use Config::General; @@ -50,6 +51,13 @@ sub new { my $now_dt = strftime "%Y-%m-%d %H:%M:%S", localtime; my $now_date = strftime "%Y-%m-%d", localtime; +my $strp = DateTime::Format::Strptime->new( + pattern => '%Y-%m-%dT%H:%M:%S', + locale => 'de_DE', + time_zone => 'Europe/Berlin', + on_error => 'croak', +); + my $lang="de"; my $owner=188;#via API my $dbh = ""; @@ -60,7 +68,7 @@ sub fetch_merchant { my $q = shift; my $varenv = shift; my $req_coo = shift || ""; - my $req_merchant_id = shift || ""; + my $req_merchant_id = shift || "$dbt->{appsframe}->{'sharee.bike'}->{merchant_id}";#defaults to sharee.bike my $return = { aowner => "", @@ -885,7 +893,7 @@ sub service_work { }#end service_work -#bike reservation +#bike adhock booking sub booking_request(){ my $self = shift; my $q = shift; @@ -900,9 +908,18 @@ sub booking_request(){ my $state = $q->escapeHTML($q->param('state')) || ""; my $lock_state = $q->escapeHTML($q->param('lock_state')) || ""; + my $now_dt = DateTime->now( time_zone => "Europe/Berlin" ); + my $reserv_starttime = $q->escapeHTML($q->param('reserv_starttime')) || $now_dt; + my $reserv_endtime = $q->escapeHTML($q->param('reserv_endtime')) || $now_dt; + my $calreserv = $q->escapeHTML($q->param('calreserv')) || 0; + + my $request_para = { + start_time => $reserv_starttime, + end_time => $reserv_endtime, + }; + my $dbh = ""; my $pos_id=""; - my $now_dt = strftime "%Y-%m-%d %H:%M", localtime; my $response_state = "OK"; my $response_text = ""; @@ -1001,21 +1018,61 @@ sub booking_request(){ #Rental is only permitted if no invoice with payment_fault or opos $bw->log("Rental is only permitted if no invoice with payment_fault or opos: $sum_balance <= 1 && !$ctt_opos->{c_id}, userID: $auth->{c_id} ",$sum_balance,""); if($sum_balance <= 1 && !$ctt_opos->{c_id}){ - #2 = "requested" - $pos_id = $dbt->insert_pos($dbh,$ctt->{c_id},$ct_bike,$ct_station,$auth,$ct_tariff,$now_dt,$bike,"2",$owner,$sig_book); - $bw->log("booking_request insert_pos:",$pos_id,""); + my $booking_state = 2; + $booking_state = 7 if($calreserv); + my $timestamp = DateTime->now( time_zone => "Europe/Berlin" ); + my $now_time = $strp->parse_datetime($timestamp); + + my $dtstart = $strp->parse_datetime($reserv_starttime); + my $dtend = $strp->parse_datetime($reserv_endtime); + + my $start_loc = $dtstart->strftime("%d.%m.%Y %H:%M"); + my $end_loc = $dtend->strftime("%d.%m.%Y %H:%M"); + + if($dtend >= $now_time){ + my $until_time = $now_time->add( weeks => 4 ); + #max allowed future rental + if($dtend > $until_time){ + $response_state = "Failure 4261, 4 weeks reserv timerange"; + $response_text = "Abbruch, Reservierungen sind maximal 4 Wochen im voraus erlaubt"; + }else{ + $pos_id = $dbt->insert_pos($dbh,$ctt->{c_id},$ct_bike,$ct_station,$auth,$ct_tariff,$request_para,$bike,$booking_state,$owner,$sig_book); + $bw->log("booking_request insert_pos:",$pos_id,""); + } + }else{ + $response_state = "Failure 4260, reserv timerange"; + $response_text = "Abbruch, die Mietzeit liegt in der Vergangenheit"; + } if($pos_id){ - $response_state = "OK, bike " . $bike . " succesfully requested"; - $response_text = "Rad $bike wurde erfolgreich für 15 Min. reserviert"; $bw->log("booking_request insert contenttranspos pos_id: $pos_id\n","",""); my $update_ctt = { table => "contenttrans", c_id => $ctt->{c_id}, + mtime => "now()", + owner => $owner, }; $dbt->update_one($dbh,$update_ctt,"start_time='$now_dt'"); + # state=7 meens reserved, prevents auto available after 15min + if($calreserv){ + $response_state = "OK, bike " . $bike . " succesfully reserved"; + $response_text = "Erfolgreiche Buchung: $start_loc - $end_loc."; + } + #update waren bike state only if adhock booking + elsif(!$calreserv){ + my $update_ct = { + table => "content", + c_id => $ct_bike->{c_id}, + mtime => "now()", + owner => $owner, + }; + $response_state = "OK, bike " . $bike . " succesfully adhock requested"; + $response_text = "Rad $bike wurde erfolgreich für 15 Min. adhock reserviert"; + } + + #BVB once auto-coupon until 2023-08-31 #disabled if(1==2 && $varenv->{dbname} eq "sharee_bvb"){ @@ -1048,7 +1105,7 @@ sub booking_request(){ } }#end BVB auto-coupon - }else{ + }elsif($response_state !~ /Failure/){ $response_state="Failure 1007: booking request fails"; $response_text="Entschuldigung, es ist ein Fehler aufgetreten. Bitte kontaktieren Sie unsere hotline damit wir das Problem lösen können"; } @@ -1089,7 +1146,7 @@ sub booking_request(){ } #booking_cancel changed to booking_update -sub booking_update(){ +sub booking_update { my $self = shift; my $q = shift; my $varenv = shift; @@ -1097,13 +1154,15 @@ sub booking_update(){ my $owner = shift || 0; my $sig_book = shift || {}; my $dbh = ""; + my $rows = 0; + my $user_agent = $q->user_agent(); my $state = $q->escapeHTML($q->param('state')) || ""; my $lock_state = $q->escapeHTML($q->param('lock_state')) || ""; - my $rows = 0; - my $user_agent = $q->user_agent(); - #my $bike = $q->param('bike'); - #my $bike_id = $1 if($q->escapeHTML($q->param('bike')) =~ /(\d+)/); + my $pos_id = $q->escapeHTML($q->param('pos_id')) || 0; + my $reserv_starttime = $q->escapeHTML($q->param('reserv_starttime')) || ""; + my $reserv_endtime = $q->escapeHTML($q->param('reserv_endtime')) || ""; + my $bike = $q->escapeHTML($q->param('bike')) || ""; my $bike_id = $bike; $bike_id =~ s/S[1-9]X/SX/; @@ -1137,9 +1196,26 @@ sub booking_update(){ fetch => "one", barcode => $bike_id, ca_id => $auth->{c_id}, - int10 => "IN::('3','2')", + int10 => "IN::('2','3')", }; + if($pos_id){ + $booking_pos->{c_id} = $pos_id; + $booking_pos->{int10} = 7; + }elsif($reserv_starttime && $reserv_endtime){ + $booking_pos->{start_time} = $reserv_starttime; + $booking_pos->{end_time} = $reserv_endtime; + $booking_pos->{int10} = 7; + } $record_pos = $dbt->fetch_tablerecord($dbh,$booking_pos) if($bike_id > 0 && $auth->{c_id} > 0); + #trying to get reserved in timerange + if($state eq "occupied" && !$record_pos->{c_id}){ + $booking_pos->{int10} = 7; + $booking_pos->{start_time} = "<=::now()"; + $booking_pos->{end_time} = ">=::now()"; + $record_pos = $dbt->fetch_tablerecord($dbh,$booking_pos) if($bike_id > 0 && $auth->{c_id} > 0); + } + $booking_values->{pos_id} = $record_pos->{c_id} || ""; + if(!$record_pos->{c_id}){ $booking_values->{response_state} = "Failure 758: Can not find bike " . $q->param('bike') . " rental or reservation on varenv-dbname: $varenv->{dbname}"; $booking_values->{response_text} = "Keine Miete oder Reservierung zu Rad " . $q->param('bike') . " gefunden."; @@ -1238,27 +1314,49 @@ sub booking_update(){ $update_pos->{txt27} = $q->escapeHTML($q->param('app_debug')) if($q->param('app_debug')); } - #if($state eq canceled && $record_pos.state eq requested && $record_pos.lock_state eq locked) - if($state_key == 6 && $record_pos->{int10} == 2 && $record_pos->{int20} == 1){ + #if($state eq canceled && $record_pos.lock_state eq locked && $record_pos.state eq requested) + if($state_key == 6 && $record_pos->{int20} == 1 && $record_pos->{int10} == 2){ $rows = $dbt->delete_content($dbh,"contenttranspos",$record_pos->{c_id}); if($rows > 0){ - $update_cc->{int10} = 1 if($record_cc->{int10} == 2);#only if still requested $booking_values->{response_state} = "OK: canceled bike " . $q->param('bike'); $booking_values->{response_text} = "Rad " . $q->param('bike') . " wurde erfolgreich storniert"; $booking_values->{state} = "available"; }else{ $booking_values->{response_state} = "Failure 2002: cancel bike " . $q->param('bike') . " fails, bike not requested"; - $booking_values->{response_text} = "Keine Reservierung zu Rad " . $q->param('bike') . " gefunden."; + $booking_values->{response_text} = "Keine adhock Reservierung zu Rad " . $q->param('bike') . " gefunden."; } - }else{ + } + #canceled reserved + elsif($state_key == 6 && $record_pos->{int20} == 1 && $record_pos->{int10} == 7){ + my $timestamp = DateTime->now( time_zone => "Europe/Berlin" ); + my $now_time = $strp->parse_datetime($timestamp); + my $reserv_starttime = DateTime::Format::Pg->parse_datetime($record_pos->{start_time}); + + #TODO define minmax hours before cancel reservation + if($now_time < $reserv_starttime){ + $rows = $dbt->delete_content($dbh,"contenttranspos",$record_pos->{c_id}); + if($rows > 0){ + $booking_values->{response_state} = "OK: canceled reserved bike " . $q->param('bike'); + $booking_values->{response_text} = "Gebuchtes Rad " . $q->param('bike') . " wurde erfolgreich storniert"; + $booking_values->{state} = "available"; + }else{ + $booking_values->{response_state} = "Failure 2082: cancel reserved bike " . $q->param('bike') . " fails, bike not reserved"; + $booking_values->{response_text} = "Keine Buchung zu Rad " . $q->param('bike') . " gefunden."; + } + }else{ + $booking_values->{response_state} = "Failure 2092: cancel reserved bike " . $q->param('bike') . " fails, too late"; + $booking_values->{response_text} = "Reservierung " . $q->param('bike') . " kann max. 1 Stunde vor Buchungsstart storniert werden."; + } + } + else{ #prevent reset occupied values OR only if genkey defined #if(($state eq "occupied" && $record_pos->{txt10} =~ /requested/) || ($state eq "occupied" && $record_pos->{txt10} =~ /occupied/ && $q->param('genkey') eq "1")) - if(($state_key == 3 && $record_pos->{int10} == 2) || ($state_key == 3 && $record_pos->{int10} == 3 && $q->param('genkey') eq "1")){ + if(($state_key == 3 && ($record_pos->{int10} == 2 || $record_pos->{int10} == 7)) || ($state_key == 3 && $record_pos->{int10} == 3 && $q->param('genkey') eq "1")){ $update_pos->{start_time} = "now()"; - $update_pos->{end_time} = "now()"; + #$update_pos->{end_time} = "now()";#don't set anymore because of revserv time $update_pos->{txt05} = "$record_cc->{txt06}";#pos start GPS from content end GPS $update_pos->{int06} = "$record_cc->{int04}";#pos start station from content station $update_pos->{txt12} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}";#pos start station prefix @@ -1292,12 +1390,16 @@ sub booking_update(){ #client GPS must have. sigo ist done without client gps - if(($gps_data->{gps} && $gps_data->{gps_age_minutes} <= 3) || ($record_pos->{int11} == 3)){ + #if(($gps_data->{gps} && $gps_data->{gps_age_minutes} <= 3) || ($record_pos->{int11} == 3)){ + #2024-03-15 app secures gps_age, we don't need it + if($gps_data->{gps} || $record_pos->{int11} == 3){ #geofencing for Ilockit my $geo_distance_next = 100000; my $station_next = 0; my $geo_debug=""; my $rows_end = 0; + + #TODO stations_available on A-A out-of-geofence have to be checked my ($stations,$stations_raw) = $self->stations_available($q,$varenv,$auth,$record_pos,""); foreach my $id (sort { $stations_raw->{$a}->{barcode} <=> $stations_raw->{$b}->{barcode} } keys (%$stations_raw)){ @@ -1415,8 +1517,8 @@ sub booking_update(){ $booking_values->{response_state} = "Failure 2012: occupied bike " . $q->param('bike') . " cannot be state $state and $lock_state"; $booking_values->{response_text} = "Rad " . $q->param('bike') . " ist in Benutzung und kann somit nicht storniert werden."; }elsif($state_key == 3 && $record_pos->{int10} == 1){ - $booking_values->{response_state} = "Failure 2016: available bike " . $q->param('bike') . " have to be at first reserved, thats because cannot be $state"; - $booking_values->{response_text} = "Rad " . $q->param('bike') . " wurde nicht reserviert und kann somit nicht gemietet werden."; + $booking_values->{response_state} = "Failure 2016: available bike " . $q->param('bike') . " have to be at first requested, thats because cannot be $state"; + $booking_values->{response_text} = "Rad " . $q->param('bike') . " wurde nicht requested und kann somit nicht gemietet werden."; }else{ $booking_values->{response_state} = "Failure 2035: bike " . $q->param('bike') . " state change to state $state and $lock_state not possible."; @@ -1600,15 +1702,15 @@ sub smartlock { $lock_value = 1; $update_cc->{int20} = "$lock_value"; $update_pos->{int20} = "$lock_value"; - $update_pos->{end_time} = "now()"; + #$update_pos->{#end_time} = "now()"; $update_cc->{txt06} = $gps_data->{gps};#end content coordinates $update_pos->{txt06} = $gps_data->{gps};#end pos coordinates $update_pos->{int21} = $gps_data->{gps_age_minutes}; $update_pos->{int22} = $gps_data->{gps_accuracy}; $update_pos->{int23} = "null";# only computed on rental-end - $booking_values->{response_state} = "OK: bike " . $q->param('bike') . " locked confirmed. "; - $booking_values->{response_text} = "Schloss schließen von Rad " . $q->param('bike') . " bestätigt. "; + $booking_values->{response_state} = " OK: bike " . $q->param('bike') . " locked confirmed. "; + $booking_values->{response_text} .= " Schloss schließen von Rad " . $q->param('bike') . " bestätigt. "; }elsif($q->param('lock_state') eq "unlocked"){ $lock_value = 2; @@ -1810,9 +1912,43 @@ sub rental_to_feedback{ }#end rental_to_feedback +#blocked bikes, reserved from now until +4 weeks +sub bikes_reserved { + my $self = shift; + my $q = shift; + my $dbh = shift; + + my $timestamp = DateTime->now( time_zone => "Europe/Berlin" ); + my $start_time = $timestamp->strftime("%Y-%m-%d %H:%M"); + my $now_time = $strp->parse_datetime($timestamp); + my $until_time = $now_time->add( weeks => 4 ); + my $end_time = $until_time->strftime("%Y-%m-%d %H:%M"); + + if($q->param('request') eq "booking_request" && $q->param('reserv_starttime') && $q->param('reserv_endtime')){ + $start_time = $q->escapeHTML($q->param('reserv_starttime')); + $end_time = $q->escapeHTML($q->param('reserv_endtime')); + } + + my $pref = { + table_pos => "contenttranspos", + fetch => "all", + keyfield => "c_id", + int10 => "IN::('2','3','7')", + template_id => 205, + start_date_time => $start_time, + end_date_time => $end_time, + }; + + my $record = {}; + $record = $dbt->collect_transpos($dbh,$pref); + + return $record; +} + #user bikes occupied sub user_bikes_occupied { my $self = shift; + my $q = shift; my $dbh = shift; my $auth = shift; my $show_dialog = shift || ""; @@ -1825,9 +1961,20 @@ sub user_bikes_occupied { template_id => "218",#Faktura tpl_id keyfield => "c_id", ca_id => "$auth->{c_id}", - int10 => "IN::('3','2')", + int10 => "IN::('2','3')", "ct.close_time" => "is::null", }; + + if($q->param('calreserv')){ + $pref->{int10} = "IN::('2','3','7')"; + $pref->{end_time} = ">=::now()"; + } + + if($q->param('request') eq "booking_request"){ + $pref->{int10} = "IN::('2','3','7')"; + $pref->{start_time} = ">=::now()"; + } + $pref->{int06} = $station if($station);#pos start-station my $record = {}; @@ -1887,7 +2034,7 @@ sub rentals(){ #bikes_available -sub bikes_available(){ +sub bikes_available { my $self = shift; my $q = shift; my $varenv_prim = shift; @@ -1899,6 +2046,9 @@ sub bikes_available(){ my $station = $q->escapeHTML($q->param('station')) || ""; my $station_id = ""; $station_id = $1 if($station =~ /(\d+)$/); + my $station_gps = ""; + $station_gps = $q->escapeHTML($q->param('Lat')) || ""; + $station_gps .= ", " . $q->escapeHTML($q->param('Lng')) || "";#TOD check space after , #to get A-A key for text my $pref_st = { @@ -1910,6 +2060,7 @@ sub bikes_available(){ }; my $record_st = {}; $pref_st->{int04} = "$station_id" if($station_id); + $pref_st->{txt06} = "$station_gps" if($station_gps); $record_st = $dbt->fetch_record($dbh,$pref_st); my $bike = $q->escapeHTML($q->param('bike')) || ""; @@ -1926,6 +2077,8 @@ sub bikes_available(){ template_id => "205", int10 => "1",#1 = "available" }; + $pref->{int10} = "IN::('1','2','3')" if($q->param('calreserv'));#take all on calreserv + my $tariff_content = {}; my $adrtarif_hash = {}; $authed = 1 if(ref($auth) eq "HASH" && $auth->{c_id} > 0); @@ -1948,8 +2101,7 @@ sub bikes_available(){ my $record = {}; $record = $dbt->fetch_record($dbh,$pref) if(ref($bike_node) eq "ARRAY" && @{$bike_node}[0]); my $op_return = {}; - - my $td_template = $dbt->rental_description_template($varenv_prim); + my $td_template = $dbt->rental_description_template($varenv_prim); #return list of occupied/requested bikes my $adjust_freedtime = 0; @@ -1959,7 +2111,17 @@ sub bikes_available(){ $further_freedtime_available = $pri->count_freedrental("rentals by bikes_available",$varenv,$auth->{c_id},$cttpos->{$id},$adjust_freedtime); } + my $bikes_blocked = {}; + $bikes_blocked = $self->bikes_reserved($q,$dbh) if($R::calreserv); + foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ + #return all reserved bikes + foreach my $rid (sort { $bikes_blocked->{$a}->{barcode} <=> $bikes_blocked->{$b}->{barcode} } keys (%$bikes_blocked)){ + if($record->{$id}->{barcode} == $bikes_blocked->{$rid}->{barcode}){ + $return->{$id}->{blocked}->{$rid}->{start_time} = $bikes_blocked->{$rid}->{start_time}; + $return->{$id}->{blocked}->{$rid}->{end_time} = $bikes_blocked->{$rid}->{end_time}; + } + } $return->{$id}->{authed} = "$authed"; $return->{$id}->{station} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{int04}"; $return->{$id}->{aa_ride} = "0"; @@ -2113,10 +2275,7 @@ sub bikes_all(){ if(looks_like_number($bike_id)){ $pref->{ barcode} = "=::$bike_id"; #2022-12-02 not select occupied bikes in servicetool by direct select-bike - $pref->{int10} = "!=::3"; - #}else{ - #2023-05-23 not select requested and occupied bikes in servicetool by list-bikes? - #$pref->{int10} = "IN::(1,4,5,6)"; + #$pref->{int10} = "!=::3";#restriction disabled } my $record = {}; @@ -2201,10 +2360,11 @@ sub bikes_all(){ #if($q->param('authcookie') && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} == 187 && scalar(@{$user_tour} >= 1)){ if($q->param('authcookie') && $varenv->{merchant_id} && $varenv->{merchant_id} eq $dbt->{appsframe}->{shareetool}->{merchant_id} && scalar(@{$user_tour} >= 1)){ #2023-01-18 temporarly for Konstanz deactivated - if(${$user_tour}[0] !~ /KN\d/){ + #2024-04-08 activated + #if(${$user_tour}[0] !~ /KN\d/){ my @service_code = split(/\s/,$record->{$id}->{txt23}); $return->{$id}->{service_code} = [@service_code]; - } + #} } }elsif($record->{$id}->{int11} eq "3"){ $return->{$id}->{system} = "sigo"; @@ -2368,12 +2528,14 @@ sub stations_available(){ if($record->{$id}->{int04} == $record_bikes->{$b_id}->{int04}){ push @bike_ids,$dbt->{operator}->{$varenv->{dbname}}->{oprefix} . $record_bikes->{$b_id}->{barcode}; $bike_count++; - $fleed = { + if($record_bikes->{$b_id}->{fleed_phone} && $record_bikes->{$b_id}->{fleed_email}){ + $fleed = { name => "$record_bikes->{$b_id}->{fleed_name}", hours => "$record_bikes->{$b_id}->{fleed_hours}", phone => "$record_bikes->{$b_id}->{fleed_phone}", email => "$record_bikes->{$b_id}->{fleed_email}", - }; + }; + } } } @@ -2436,6 +2598,8 @@ sub stations_available(){ operator_email => $hotline_data->{txt08}, }; } + #$return->{$id}->{operator_data}->{operator_name} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$return->{$id}->{operator_data}->{operator_name})) if($return->{$id}->{operator_data}->{operator_name}); + #$return->{$id}->{operator_data}->{operator_hours} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$return->{$id}->{operator_data}->{operator_hours})) if($return->{$id}->{operator_data}->{operator_hours}); #not desired 2024-02-15 if(1==2){ @@ -3183,7 +3347,7 @@ sub auth_verify(){ my $last_used_operator = $record->{txt19};#check if this is primary and/or useable #$bw->log("last_used_operator selected by txt19:",$last_used_operator,""); if($last_used_operator){ - my $dbh_operator = $dbt->dbconnect_extern("$last_used_operator","iso-8859-1"); + my $dbh_operator = $dbt->dbconnect_extern("$last_used_operator",""); my $hotline_hash = { table => "contentuser", fetch => "one", @@ -3198,8 +3362,10 @@ sub auth_verify(){ "operator_phone" => "", "operator_email" => "", }; - $return->{last_used_operator}->{operator_name} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$hotline_data->{txt01})) if($hotline_data->{txt01}); - $return->{last_used_operator}->{operator_hours} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$hotline_data->{txt84})) if($hotline_data->{txt84}); + #$return->{last_used_operator}->{operator_name} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$hotline_data->{txt01})) if($hotline_data->{txt01}); + #$return->{last_used_operator}->{operator_hours} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$hotline_data->{txt84})) if($hotline_data->{txt84}); + $return->{last_used_operator}->{operator_name} = $hotline_data->{txt01} if($hotline_data->{txt01}); + $return->{last_used_operator}->{operator_hours} = $hotline_data->{txt84} if($hotline_data->{txt84}); $return->{last_used_operator}->{operator_phone} = $hotline_data->{txt07} if($hotline_data->{txt07}); $return->{last_used_operator}->{operator_email} = $hotline_data->{txt08} if($hotline_data->{txt08}); } diff --git a/copri4/main/src/Mod/APIjsonclient.pm b/copri4/main/src/Mod/APIjsonclient.pm index e5ac995..2b31dbd 100755 --- a/copri4/main/src/Mod/APIjsonclient.pm +++ b/copri4/main/src/Mod/APIjsonclient.pm @@ -84,7 +84,10 @@ sub loop_sharees { $bw->log("shareetool select_users $return_merchant->{aowner} on $op_name->{database}->{dbname} $authraw->{c_id} $authraw->{txt17}",$users_serviceapp->{u_id},""); } #every sharee client must have a merchant_id which associate a project - if($op_name->{operatorApp} && ($users_serviceapp->{u_id} || $return_merchant->{merchant_id} eq $globalconf{website}->{'shareeweb-sharee'}->{merchant_id} || ($return_merchant->{project_id} eq $op_name->{project}))){ + #shareeweb gets all ($return_merchant->{merchant_id} eq $globalconf{website}->{'shareeweb-sharee'}->{merchant_id) + #sharee.bike gets also Bayern + #print $bw->log("Operator getter if($op_name->{operatorApp} && ($users_serviceapp->{u_id} || $return_merchant->{merchant_id} eq $globalconf{website}->{'shareeweb-sharee'}->{merchant_id} || ($return_merchant->{project_id} eq $op_name->{project}))){","",""); + if($op_name->{operatorApp} && ($users_serviceapp->{u_id} || $return_merchant->{merchant_id} eq $globalconf{website}->{'shareeweb-sharee'}->{merchant_id} || ($return_merchant->{project_id} eq $op_name->{project}) || ($return_merchant->{project_id} eq "Freiburg" && $op_name->{project} eq "Bayern"))){ $o++; #stations_available with optional caching if($rest_hash->{request} eq "stations_available"){ @@ -252,9 +255,10 @@ sub fetch_operator_json { my $self = shift; my $operator_server = shift || ""; my $rest = shift || ""; - my $operator_request = "$operator_server?$rest"; + my $operator_request = "$operator_server"; + $operator_request = "$operator_server?$rest" if($rest); - #$bw->log("fetch_operator_json >> $operator_request","$operator_request",""); + $bw->log("fetch_operator_json >> $operator_server","$operator_request",""); my $req = HTTP::Request->new(GET => "$operator_request"); $req->content_type('application/x-www-form-urlencoded'); $req->content($rest); diff --git a/copri4/main/src/Mod/APIjsonserver.pm b/copri4/main/src/Mod/APIjsonserver.pm index 63c84f5..6ccb982 100755 --- a/copri4/main/src/Mod/APIjsonserver.pm +++ b/copri4/main/src/Mod/APIjsonserver.pm @@ -71,7 +71,7 @@ my $response = { apiserver => "$apiserver", response => "$respreq", uri_primary => "$dbt->{primary}->{sharee_primary}->{primaryApp}", - copri_version => "4.1.23.29", + copri_version => "4.1.23.30", user_id => "", authcookie => "", new_authcoo => "0", @@ -243,18 +243,31 @@ elsif($q->param('request') eq "booking_request"){ $bike_id = $1 if($bike_id =~ /(\d+)/); #check count of occcupied/requested bikes - my $record = $apif->user_bikes_occupied($dbh,$authraw,""); + my $record = {}; my $max_rental_count = 3; $max_rental_count = 10 if($authraw->{int09}); my $rental_count=0; my $still_requested = 0; - foreach my $id (keys(%$record)){ + if($R::calreserv){ + $record = $apif->bikes_reserved($q,$dbh); + foreach my $id (keys(%$record)){ + if($bike_id && $bike_id == $record->{$id}->{barcode}){ + $still_requested = 1; + $response->{response_state} = "OK, bike " . $bike . " already in timerange reserved"; + $response->{response_text} = "Rad " . $bike . " ist für diesen Zeitraum nicht verfügbar."; + } + } + + }else{ + $record = $apif->user_bikes_occupied($q,$dbh,$authraw,""); + foreach my $id (keys(%$record)){ $rental_count++; if($bike_id && $bike_id == $record->{$id}->{barcode}){ $still_requested = 1; $response->{response_state} = "OK, bike " . $bike . " already requested or occupied"; - $response->{response_text} = "Fahrrad Nr. " . $bike . " ist bereits reserviert"; + $response->{response_text} = "Rad " . $bike . " ist bereits reserviert"; } + } } if(!$still_requested){ @@ -293,7 +306,7 @@ elsif($q->param('request') eq "booking_request"){ rentalId => "", }; - if(!$ct_bike->{barcode} || !$ct_bike->{int10} || $ct_bike->{int10} != 1){ + if(!$ct_bike->{barcode} || !$ct_bike->{int10}){ $response->{response_state} = "Failure 2001: booking bike $bike fails, bike not available"; $response->{response_text} = "Mietrad $bike ist nicht verfügbar. Ist das Mietrad für sie freigeschaltet? Bitte überprüfen Sie Ihre Profildaten auf Vollständigkeit"; }elsif(!$ct_tariff->{barcode}){#ist will not happen, because of prios tariff select in fetch_bike_tariff @@ -318,7 +331,7 @@ elsif($q->param('request') eq "booking_request"){ table => "contenttranspos", fetch => "one", barcode => "$bike_id", - int10 => "2", + int10 => "IN::('2','7')", ca_id => "$authraw->{c_id}", }; my $dbh = ""; @@ -342,7 +355,7 @@ elsif($q->param('request') eq "booking_request"){ } #return list of occupied/requested bikes - $record = $apif->user_bikes_occupied($dbh,$authraw,""); + $record = $apif->user_bikes_occupied($q,$dbh,$authraw,""); $response->{bikes_occupied} = $apif->rentals(\%varenv,$record,$authraw,"1");#returns JSON rental values }#end still_requested @@ -379,7 +392,7 @@ elsif($q->param('request') eq "booking_cancel" || $q->param('request') eq "booki $bike_id =~ s/S[1-9]X/SX/; $bike_id = $1 if($bike_id =~ /(\d+)/); - my $ctpos = {}; + my $ctpos = {};#can be removed after sig my $booking_pos = { table => "contenttranspos", fetch => "one", @@ -426,7 +439,7 @@ elsif($q->param('request') eq "booking_cancel" || $q->param('request') eq "booki ($rows, $booking_values) = $apif->booking_update($q,\%varenv,$authraw,$aowner,$sig_book); $response = {%$response, %$booking_values}; - my $record = $apif->user_bikes_occupied($dbh,$authraw,"show_dialog"); + my $record = $apif->user_bikes_occupied($q,$dbh,$authraw,"show_dialog"); $response->{bikes_occupied} = $apif->rentals(\%varenv,$record,$authraw,"1"); #update on Ilockit @@ -435,12 +448,12 @@ elsif($q->param('request') eq "booking_cancel" || $q->param('request') eq "booki $apif->stations_caching($q,\%varenv,$authraw); $response = {%$response, %$booking_values}; - my $record = $apif->user_bikes_occupied($dbh,$authraw,""); + my $record = $apif->user_bikes_occupied($q,$dbh,$authraw,""); $response->{bikes_occupied} = $apif->rentals(\%varenv,$record,$authraw,"1"); } }#end occupied|available else{ - my $record = $apif->user_bikes_occupied($dbh,$authraw,""); + my $record = $apif->user_bikes_occupied($q,$dbh,$authraw,""); $response->{bikes_occupied} = $apif->rentals(\%varenv,$record,$authraw,"1"); } @@ -478,7 +491,7 @@ elsif($q->param('request') eq "user_bikes_occupied"){ ($auth,$authraw) = $apif->auth_verify($q); if(ref($auth) eq "HASH" && $auth->{authcookie}){ $response = { %$response, %$auth }; - my $record = $apif->user_bikes_occupied($dbh,$authraw,"show_dialog"); + my $record = $apif->user_bikes_occupied($q,$dbh,$authraw,"show_dialog"); if($R::withoutkey){ $response->{bikes_occupied} = $apif->rentals(\%varenv,$record,$authraw,""); }else{ @@ -531,9 +544,12 @@ elsif($q->param('request') eq "bikes_available"){ my $station_id = ""; $station_id = $1 if($station =~ /(\d+)$/); - $record = $apif->user_bikes_occupied($dbh,$authraw,"",$station_id); + $record = $apif->user_bikes_occupied($q,$dbh,$authraw,"",$station_id); $response->{bikes_occupied} = $apif->rentals(\%varenv,$record,$authraw,"1");#returns JSON rental values } + + #$response->{bikes_blocked} = $apif->bikes_reserved($q,$dbh) if($R::calreserv); + } if(ref($response->{bikes}) ne "HASH"){ $response->{response_state} = "Failure 5003: cannot find any user defined bike tariff"; @@ -742,13 +758,15 @@ elsif($q->param('request') eq "stations_available"){ } #App merchant message + #if($user_agent =~ /konrad/i && $dbt->{copri_conf}->{betau_id}->{$authraw->{c_id}} && $varenv{cms}->{'App-merchant-message'}->{txt}){ if($user_agent =~ /konrad/i && $varenv{cms}->{'App-merchant-message'}->{txt}){ #if($epoch_now >= $epoch_start && $epoch_now <= $epoch_end){ $response->{merchant_message} = $varenv{cms}->{'App-merchant-message'}->{txt}; #} } #App merchant message bayern - if($user_agent =~ /bayern/i && $varenv{cms}->{'App-merchant-message-bayern'}->{txt}){ + #if($user_agent =~ /bayern/i && $varenv{cms}->{'App-merchant-message-bayern'}->{txt}){ + if($user_agent =~ /bayern/i && $user_agent_subversion <= 380 && $varenv{cms}->{'App-merchant-message-bayern'}->{txt}){ #if($epoch_now >= $epoch_start && $epoch_now <= $epoch_end){ $response->{merchant_message} = $varenv{cms}->{'App-merchant-message-bayern'}->{txt}; #} diff --git a/copri4/main/src/Mod/DBtank.pm b/copri4/main/src/Mod/DBtank.pm index 84d13d7..1609106 100755 --- a/copri4/main/src/Mod/DBtank.pm +++ b/copri4/main/src/Mod/DBtank.pm @@ -876,6 +876,8 @@ sub fetch_tablerecord(){ $where .= " and $key $op $value"; }elsif($op eq "IN"){ $where .= " and $key $op $value"; + }elsif($op eq "NOT IN"){ + $where .= " and $key $op $value"; }else{ $where .= " and $key $op '$value'"; } @@ -894,12 +896,10 @@ sub fetch_tablerecord(){ }elsif($key =~ /^(c_id|u_id|cc_id|ct_id|ca_id|barcode|int\d+|owner|template_id)$/ && (looks_like_number($value) || $value eq "null")){ if($value eq "null"){ $where .= " and ($key is null OR $key = 0)"; - }elsif($value eq "nullOR1"){ - $where .= " and ($key is null OR $key = 1)"; }else{ $where .= " and $key $op $value"; } - }elsif($key =~ /int\d+/ && $op eq "IN"){ + }elsif($key =~ /int\d+|template_id/ && $op eq "IN"){ $where .= " and $key $op $value"; } } @@ -917,7 +917,7 @@ sub fetch_tablerecord(){ my $rc = $sth->execute(); #debug $fetch->{table} eq "contenttranspos" on Failure 758 - #$bw->log("DBtank fetch_tablerecord source-dbname $source:",$sql,"") if($debug && $fetch->{table} eq "contenttranspos"); + $bw->log("DBtank fetch_tablerecord source-dbname $source:",$sql,"") if($debug && $fetch->{table} eq "contenttranspos"); my $record = { c_id => 0 }; if($fetch->{fetch} eq "all" && $fetch->{keyfield}){ @@ -1239,8 +1239,10 @@ sub collect_transpos { $search->{offset} = 0 if(!$search->{offset}); - my $where = "where cp.ct_id=ct.c_id"; + my $where = "where 1=1"; + $where .= " and cp.ct_id=ct.c_id" if($search->{table}); $where .= " and cp.int05 is null";#do not select sub workflow docs like storno + foreach my $key (keys (%$search)){ $search->{$key} =~ s/^\s//g; $search->{$key} =~ s/\s$//g; @@ -1256,6 +1258,7 @@ sub collect_transpos { $where .= " and cp.$key = $search->{$key}" if($key eq "int20" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "barcode" && looks_like_number($search->{$key})); $where .= " and cp.$key = $search->{$key}" if($key eq "int12" && looks_like_number($search->{$key})); + $where .= " and cp.$key = $search->{$key}" if($key eq "template_id" && looks_like_number($search->{$key})); $where .= " and (cp.$key = $search->{$key} OR cp.owner_end = $search->{$key})" if($key eq "owner" && looks_like_number($search->{$key})); $where .= " and (cp.$key is $search->{$key} OR cp.$key = 0)" if($key eq "int34" && $search->{$key} eq "null"); $where .= " and cp.$key ilike '%$search->{$key}%'" if($key eq "txt23" && $search->{$key}); @@ -1267,24 +1270,31 @@ sub collect_transpos { #adding itime to get also not rental dependent entries if($search->{start_date_time} && $search->{end_date_time}){ - $where .= " and ((cp.end_time >= '$search->{start_date_time}' and cp.end_time <= '$search->{end_date_time}' and cp.start_time <= '$search->{end_date_time}') OR (cp.itime >= '$search->{start_date_time}' and cp.itime <= '$search->{end_date_time}'))"; + my $or_itime = ""; + #because of bikes_reserved, don't search others when bike is requested + if(!$search->{template_id} || $search->{template_id} != 205){ + $or_itime = "OR (cp.itime >= '$search->{start_date_time}' and cp.itime <= '$search->{end_date_time}')"; + } + $where .= " and ((cp.end_time >= '$search->{start_date_time}' and cp.end_time <= '$search->{end_date_time}' and cp.start_time <= '$search->{end_date_time}') $or_itime)"; + }elsif($search->{start_time_interval}){ $where .= " and cp.start_time <= $search->{start_time_interval}"; } $where .= " ORDER BY cp.c_id DESC LIMIT $search->{limit} OFFSET $search->{offset}" if($search->{limit}); - my $sql = "SELECT cp.* from $search->{table} cp, contenttrans ct $where"; - #2024-02-22 not used anymore - #for system messaging - #if($messaging){ - # $sql = "SELECT cp.*,ct.txt07 AS phone,ct.txt08 AS email,ct.txt11 AS lang from $search->{table} cp, contenttrans ct $where"; - #} + my $sql = ""; + if($search->{table}){ + $sql = "SELECT cp.* from $search->{table_pos} cp, $search->{table} ct $where"; + }else{ + $sql = "SELECT cp.* from $search->{table_pos} cp $where"; + } + my $sth = $dbh->prepare($sql); my $rc = $sth->execute(); my $ct = $sth->fetchall_hashref("c_id"); - #$bw->log("collect_transpos",$sql,"") if($debug); + $bw->log("collect_transpos",$sql,"") if($debug); return $ct; -} +}#end collect_transpos #collect contenttheftpos sub collect_theftpos { @@ -1534,13 +1544,14 @@ sub insert_pos(){ my $self = shift; my $dbh = shift || $dbh_intern; my $ctt_id = shift; - my $ct = shift || {}; + my $ct = shift || {};#bike or part content my $ct_station = shift || {}; my $ctadr = shift || {}; - my $ct_tariff = shift || ""; - my $endRental = shift || "0000-00-00"; + my $ct_tariff = shift || {}; + #my $endRental = shift || "0000-00-00"; + my $request_para = shift || {}; my $ct_name = shift || ""; - my $status = shift || ""; + my $booking_state = shift || ""; my $owner = shift || ""; my $sig_book = shift || {}; @@ -1601,7 +1612,7 @@ sub insert_pos(){ my $sth; #Verleihräder if($ct->{template_id} && $ct->{template_id} == 205){#Leihrad_list - $sth = $dbh->prepare("INSERT INTO contenttranspos (ct_id,cc_id,ca_id,ct_name,barcode,txt01,txt08,txt02,txt09,txt12,itime,start_time,end_time,int01,int02,int03,int06,txt05,txt06,txt07,int10,int12,template_id,int13,owner,int07,txt04,int09,int17,int15,int11,int18,int19,txt17,txt18,int20,int25,int29,int34,txt22,txt11,int35,int36,int37,int42,time01,time02) VALUES ('$ctt_id','$ct->{c_id}','$ctadr->{c_id}','$ct_name','$ct->{barcode}','$ct->{txt01}','$user_name','$ct->{txt02}','$ctadr->{txt09}','$prefix',now(),now(),'$endRental','1','$unit_price','$menge','$start_station','$ct->{txt06}','$ct->{txt06}','$ct->{txt07}','$status','$from_main_id','$from_template_id','$deviceId','$owner','$rabatt','$tariff_desc','$tariff_nr','$daymax_price','$abo_price','$ct->{int11}','$sharing_type','$bike_charge','$ct->{txt17}','$ct->{txt18}','1','$trackon','$bike_type_id','$staff','$sig_book->{bikeId}','$sig_book->{rentalId}','$unit_price1','$unit_price2','$start_price','$aa_station','$unit_time','$free_time') RETURNING c_id"); + $sth = $dbh->prepare("INSERT INTO contenttranspos (ct_id,cc_id,ca_id,ct_name,barcode,txt01,txt08,txt02,txt09,txt12,itime,start_time,end_time,int01,int02,int03,int06,txt05,txt06,txt07,int10,int12,template_id,int13,owner,int07,txt04,int09,int17,int15,int11,int18,int19,txt17,txt18,int20,int25,int29,int34,txt22,txt11,int35,int36,int37,int42,time01,time02) VALUES ('$ctt_id','$ct->{c_id}','$ctadr->{c_id}','$ct_name','$ct->{barcode}','$ct->{txt01}','$user_name','$ct->{txt02}','$ctadr->{txt09}','$prefix',now(),'$request_para->{start_time}','$request_para->{end_time}','1','$unit_price','$menge','$start_station','$ct->{txt06}','$ct->{txt06}','$ct->{txt07}','$booking_state','$from_main_id','$from_template_id','$deviceId','$owner','$rabatt','$tariff_desc','$tariff_nr','$daymax_price','$abo_price','$ct->{int11}','$sharing_type','$bike_charge','$ct->{txt17}','$ct->{txt18}','1','$trackon','$bike_type_id','$staff','$sig_book->{bikeId}','$sig_book->{rentalId}','$unit_price1','$unit_price2','$start_price','$aa_station','$unit_time','$free_time') RETURNING c_id"); }else{ $sth = $dbh->prepare("INSERT INTO contenttranspos (ct_id,cc_id,ca_id,ct_name,barcode,txt08,itime,int01,int02,int03,txt01,int10,int12,int16,template_id,owner) VALUES ('$ctt_id','$ct->{c_id}','$ctadr->{c_id}','$ct_name','$ct->{barcode}','$user_name',now(),'1','$unit_price','1','$ct->{txt01}','0','$from_main_id','$fibumark','$from_template_id','$owner') RETURNING c_id"); } @@ -1610,15 +1621,6 @@ sub insert_pos(){ $sth->bind_columns(\$last_id); my $c_id = $sth->fetchrow_array(); - if($c_id && $status){ - #update Leihräder in Stammdaten - my $set2 = "owner=$owner" if($owner); - $set2 .= ",int10='$status'" if($status); - $set2 .= ",mtime='now()'"; - my $sth2 = $dbh->prepare("UPDATE content SET $set2 where c_id='$ct->{c_id}'"); - my $rows2 = $sth2->execute(); - } - return $c_id; } diff --git a/copri4/main/src/Mod/GBFSout.pm b/copri4/main/src/Mod/GBFSout.pm index 92bdb2d..8352d13 100755 --- a/copri4/main/src/Mod/GBFSout.pm +++ b/copri4/main/src/Mod/GBFSout.pm @@ -39,6 +39,7 @@ sub handler { my %varenv = $cf->envonline(); my $coo = $q->cookie('domcookie') || $R::sessionid || ""; + my $station_select = $R::station || ""; my $users_sharee = { c_id => 0 }; my $api_return = { authcookie => '' }; @@ -63,14 +64,14 @@ sub handler { #request primary will jsonclient loop_sharees my $uri_request = $dbt->{primary}->{sharee_primary}->{primaryApp}; - #detect DMS, because this will do it directly without loop_sharees - $uri_request = $dbt->{operator}->{$varenv{dbname}}->{operatorApp} if($varenv{dbname} ne $dbt->{primary}->{sharee_primary}->{database}->{dbname} && $varenv{syshost} =~ /shareedms-/); + #detect operator, because this will do it directly without loop_sharees + $uri_request = $dbt->{operator}->{$varenv{dbname}}->{operatorApp} if($varenv{dbname} ne $dbt->{primary}->{sharee_primary}->{database}->{dbname}); if($R::request eq "stations_available"){ station_information($api_return,\%varenv,$users_sharee,$uri_request,$project); } if($R::request eq "bikes_available"){ - vehicle_status($api_return,\%varenv,$users_sharee,$uri_request,$project); + vehicle_status($api_return,\%varenv,$users_sharee,$uri_request,$project,$station_select); } return Apache2::Const::OK; @@ -103,6 +104,10 @@ sub station_information { $gbfs_station{$station}{bike_count} = $response_stations->{shareejson}->{stations}->{$station}->{bike_count}; $gbfs_station{$station}{lat} = $response_stations->{shareejson}->{stations}->{$station}->{gps}->{latitude}; $gbfs_station{$station}{lon} = $response_stations->{shareejson}->{stations}->{$station}->{gps}->{longitude}; + #view it only for bike reservation + if($R::calreserv){ + $gbfs_station{$station}{uri_operator} = $response_stations->{shareejson}->{stations}->{$station}->{uri_operator}; + } #$gbfs_station{$station}{is_charging_station} = 1 if(grep(/300102/, @{$response_stations->{shareejson}->{stations}->{$station}->{station_group}}));#E-L push (@gbfs_stations, $gbfs_station{$station}); } @@ -133,9 +138,11 @@ sub vehicle_status { my $users_sharee = shift || { c_id => 0 }; my $uri_request = shift || ""; my $project = shift || "all"; + my $station_select = shift || ""; my $json = JSON->new->allow_nonref; my $rest_bikes = "request=bikes_available&project=$project&authcookie=$authcookie->{authcookie}"; + $rest_bikes = "request=bikes_available&project=$project&station=$station_select&authcookie=$authcookie->{authcookie}" if($station_select); my $gbfs_resp = {}; my @gbfs_bikes = (); diff --git a/copri4/main/src/Mod/Indexsharee.pm b/copri4/main/src/Mod/Indexsharee.pm index c4cc057..9f4a2d9 100755 --- a/copri4/main/src/Mod/Indexsharee.pm +++ b/copri4/main/src/Mod/Indexsharee.pm @@ -568,12 +568,15 @@ sub handler { if($users_sharee->{c_id} && $R::sharee_edit && $R::sharee_edit =~ /save_account/){ ($returnwww,$feedb) = $shwo->save_account($dbh,$q,$users_sharee->{c_id},\%varenv,$aowner); } - if($users_sharee->{c_id} && $R::sharee_edit && $R::sharee_edit =~ /save_transact/){ + elsif($users_sharee->{c_id} && $R::sharee_edit && $R::sharee_edit =~ /save_transact/){ $returnwww = $shwo->save_transact($q,$users_sharee->{c_id},$coo,$aowner); } - if($users_sharee->{c_id} && $R::sharee_edit && $R::sharee_edit =~ /generate_payonelink/ && $R::prepaid_amount && $R::prepaid_amount =~ /\d+/){ + elsif($users_sharee->{c_id} && $R::sharee_edit && $R::sharee_edit =~ /generate_payonelink/ && $R::prepaid_amount && $R::prepaid_amount =~ /\d+/){ system("$dbt->{copri_conf}->{basedir}/$varenv{syshost}/src/scripts/payonelink.pl '$varenv{syshost}' '$users_sharee->{c_id}' '$R::prepaid_amount' '$aowner' &"); } + elsif($users_sharee->{c_id} && $R::sharee_edit && $R::sharee_edit =~ /bike_reserv/){ + $returnwww = $shwo->bike_reserv($q,\%varenv,$users_sharee->{c_id},$aowner); + } if($returnwww && $returnwww =~ /failure::(.*)/){ $returnwww =~ s/::/=/g; @@ -634,7 +637,7 @@ sub handler { $dbt->update_record($dbh,$update_adr,$users_sharee) if($users_sharee->{c_id} > 0); ($api_return,$users_sharee) = $apif->auth_verify($q,$coo,""); - #payment_ack + #payment_ack payAck system("$dbt->{copri_conf}->{basedir}/$varenv{syshost}/src/scripts/payment_ack.pl '$varenv{syshost}' 'payment_ackCC' '$users_sharee->{c_id}' '$aowner' &"); if(1==1){ @@ -726,6 +729,10 @@ sub handler { exit 0; } } + elsif(!$users_sharee->{c_id} && !$R::logedout && ($path !~ /$varenv{mandant}\/Anmelden|$varenv{mandant}\/Account/)){ + print redirect("$varenv{wwwhost}?logedout=1$session_and"); + exit 0; + } }#end web frame @@ -776,7 +783,6 @@ sub handler { }#end confirm - #Printpreview if($view =~ /Printpreview/){ require "Mod/Printpreview.pm"; @@ -803,8 +809,9 @@ sub handler { my $onload=""; my $local_style = "$varenv{metahost}/$dbt->{shareeapp_conf}->{local_style}"; - my $jquery = ""; - my $jquery_ui = ""; + #my $jquery = "$varenv{metahost}/$dbt->{copri_conf}->{jsscript}"; + my $jquery = "$varenv{metahost}/$dbt->{shareeapp_conf}->{jquery}";#used by CalReserv / rentalator.js + my $jquery_ui = "$varenv{metahost}/$dbt->{copri_conf}->{jsscript}"; my $style_jquery_ui = ""; my $js_bootstrap = "$varenv{metahost}/$dbt->{shareeapp_conf}->{js_bootstrap}"; my $style_bootstrap = "$varenv{metahost}/$dbt->{shareeapp_conf}->{style_bootstrap}"; diff --git a/copri4/main/src/Mod/MailTransport.pm b/copri4/main/src/Mod/MailTransport.pm index 839e63c..0b7e2a6 100755 --- a/copri4/main/src/Mod/MailTransport.pm +++ b/copri4/main/src/Mod/MailTransport.pm @@ -276,6 +276,8 @@ sub mail_hours_occupied { my $uadr = shift; my $contentpos = shift; my $sendref = $self->sendrefhash(); + $sendref->{mailxcfg} = "mailx_hotline"; + $sendref->{mailxcfg} = "mailx_konrad" if($varenv->{syshost} eq "shareedms-kn"); my $dbh_primary = $dbt->dbconnect_extern($dbt->{primary}->{sharee_primary}->{database}->{dbname},"iso-8859-1"); diff --git a/copri4/main/src/Mod/Payment.pm b/copri4/main/src/Mod/Payment.pm index 6960a67..1090941 100755 --- a/copri4/main/src/Mod/Payment.pm +++ b/copri4/main/src/Mod/Payment.pm @@ -927,7 +927,8 @@ sub rpc { $payoneret = $txidval; print FILE "payone CAPTURE $now_dt\n $todo: txid=$txidval && ctt.c_id=$ctt->{c_id} && ctadr.c_id=$ctadr->{c_id}\n" if($debug); - if($txidval && $ctt->{c_id} && $ctadr->{c_id} && $res->content =~ /settleaccount=/){ + #if($txidval && $ctt->{c_id} && $ctadr->{c_id} && $res->content =~ /settleaccount=/){ + if($txidval && $ctt->{c_id} && $ctadr->{c_id}){ $update_ctt->{int14} = "null"; $update_adr->{int12} = 0; }else{#because of Prelogic logic set it empty if no capture diff --git a/copri4/main/src/Mod/Prelib.pm b/copri4/main/src/Mod/Prelib.pm index 1d71ced..d062214 100755 --- a/copri4/main/src/Mod/Prelib.pm +++ b/copri4/main/src/Mod/Prelib.pm @@ -72,12 +72,11 @@ sub longterm_occupied { }; my $uadr = { c_id => 0 }; $uadr = $dbt->fetch_record($dbh,$pref_cc); - $uadr->{txt07} =~ s/\s//g; my $search = { - table => "contenttranspos", + table_pos => "contenttranspos", int10 => 3, - #int34 => "null",#if not staff TODO + int34 => "null",#if not staff start_time_interval => "(now() - interval '12 hours')", }; my $update_pos = { @@ -126,6 +125,7 @@ sub longterm_occupied { print FILE "if(!$cttpos->{$pid}->{int33} || $cttpos->{$pid}->{int33} < $h_id)\n"; print FILE "Sent message for > $h_id hour rental by $posting_sms->{$h_id}\n"; + $uadr->{txt07} =~ s/\s//g; my $contact_hotline = "Hotline $uadr->{txt01} $uadr->{txt08}, $uadr->{txt07}"; $smstrans->sms_message($h_id,$contact_hotline,$cttpos->{$pid}->{ca_id},"",$cttpos->{$pid}->{ct_name}); my $message_log = $cttpos->{$pid}->{txt20} . "\n- $log_stamp $posting_sms->{$h_id}"; @@ -963,6 +963,7 @@ sub delete_contenttranspos { table => "contenttrans", table_pos => "contenttranspos", fetch => "one", + catch => "content_contenttranspos", template_id => "219",#prepaid tpl_id c_id => $c_id, int02 => ">=::1", diff --git a/copri4/main/src/Mod/Printpreview.pm b/copri4/main/src/Mod/Printpreview.pm index 439ad36..f9c8973 100755 --- a/copri4/main/src/Mod/Printpreview.pm +++ b/copri4/main/src/Mod/Printpreview.pm @@ -276,7 +276,7 @@ td { $header_top = $header_px * ($site -1); $footer_top = $footer_px * $site + ($header_px - $footer_px -10); - $footer_top = $footer_px * $site + ($site * (0.70 * ($header_px - $footer_px))) if($site > 2); + $footer_top = $footer_px * $site + ($site * (0.75 * ($header_px - $footer_px))) if($site > 2); print PMA "2.$site) text_footer footer_top: $footer_top | $site/$site_all\n"; &text_footer(\%varenv,$ctf,$ctt,$footer_top,$site,$site_all); diff --git a/copri4/main/src/Mod/Shareework.pm b/copri4/main/src/Mod/Shareework.pm index 6ef9a71..984a158 100755 --- a/copri4/main/src/Mod/Shareework.pm +++ b/copri4/main/src/Mod/Shareework.pm @@ -52,6 +52,18 @@ my $i_rows=0; my $u_rows=0; my $d_rows=0; +#bike reservation by CalReserv +sub bike_reserv { + my $self = shift; + my $q = shift; + my $varenv = shift; + my $ca_id = shift; + my $aowner = shift; + + return; +} + + # #also done in src/Tpl/Anmelden.pm!? sub delete_account { @@ -286,10 +298,11 @@ sub save_account(){ } #Freischaltcode format can be "CA-Li-hsze789k" or "CA1234567" - if($valxx && ($valxx =~ /^(\w{2,3})-([\w\-]+)/i || $valxx =~ /^(\w{2,3})(\d+)/i)){ + if($valxx && ($valxx =~ /^(\w{2,3})-([\w\-]+)/i || $valxx =~ /^(\w{2,3})(\d+)/i || $valxx =~ /^(\w{2,3})-(\w+)/i)){ $valxx =~ s/\s//g; my $bonus_prefix = uc($1), my $bonusnr = $2; + $bonusnr = "$1-$2" if($valxx =~ /^(\w{2,3})-(\w+)/i);#TR Oberried my $operator_conf = $dbt->get_operator_conf($bonus_prefix); my @txt30_op = (); @@ -563,7 +576,7 @@ sub save_account(){ my $payone_mival = $payone->managemandate_main(\%varenv,$ctadr,"",$owner); if($payone_mival && $payone_mival =~ /\w{2}-\w+/){ - #payment_ack + #payment_ack payAck system("$dbt->{copri_conf}->{basedir}/$varenv{syshost}/src/scripts/payment_ack.pl '$varenv{syshost}' 'payment_ackSEPA' '$ctadr->{c_id}' '$owner' &"); $vde_on_fail = 0 if($vde_on_fail != 2); diff --git a/copri4/main/src/Tpl/BaseEdit.pm b/copri4/main/src/Tpl/BaseEdit.pm index a622772..6398a26 100755 --- a/copri4/main/src/Tpl/BaseEdit.pm +++ b/copri4/main/src/Tpl/BaseEdit.pm @@ -960,7 +960,7 @@ EOF table => "content", fetch => "one", template_id => "228", - ct_name => "$ctrel->{txt15}", + ct_name => "ilike::$ctrel->{txt15}", }; $bonus_record = $dbt->fetch_record($dbh,$pref_cc) if($ctrel->{txt15}); } @@ -974,11 +974,11 @@ EOF if($bonus_record->{int22} && $tf_id && $bonus_record->{int22} == $tf_id){ $postdes .= "*code aktiviert $sharing_type Tarif Nr. $bonus_record->{int22}. "; } - if((!$ctrel->{txt15} || $bonus_record->{ct_name} ne $ctrel->{txt15}) && $tf_id && $tariff_all->{$tf_id}->{int18} != 2){ + if((!$ctrel->{txt15} || $bonus_record->{ct_name} !~ /$ctrel->{txt15}/i) && $tf_id && $tariff_all->{$tf_id}->{int18} != 2){ $postdes .= $q->span({-style=>'color:red;padding-left:10px;'},"Achtung, $sharing_type Tarif $tf_id ohne *code aktiviert. "); } } - if($ctrel->{txt15} && $bonus_record->{ct_name} ne $ctrel->{txt15}){ + if($ctrel->{txt15} && $bonus_record->{ct_name} !~ /$ctrel->{txt15}/i){ $postdes .= $q->span({-style=>'color:red;padding-left:10px;'},"*code ist nicht vorhanden! "); }elsif($ctrel->{txt15} && $bonus_record->{ct_name} eq $ctrel->{txt15}){ my $sharing_type = "public-bonus"; diff --git a/copri4/main/src/Tpl/Calorin.pm b/copri4/main/src/Tpl/Calorin.pm index 245271a..e2ed674 100755 --- a/copri4/main/src/Tpl/Calorin.pm +++ b/copri4/main/src/Tpl/Calorin.pm @@ -85,6 +85,7 @@ sub tpl(){ parent_id => $dbt->{shareedms_conf}->{waren}, fetch => "all", keyfield => "main_id", + content_id => "null", }; my $part_nodes = $dbt->fetch_rel4tpl4nd($dbh,$bnode); @@ -178,7 +179,8 @@ sub tpl(){ my $cttpos = {}; $R::ct_ct_name =~ s/\#//; my $search = { - table => "$node_meta->{ct_table}", + table => "contenttrans", + table_pos => "$node_meta->{ct_table}", limit => $q->escapeHTML($limit), offset => $q->escapeHTML($offset), }; @@ -352,7 +354,7 @@ sub tpl(){ ($year_st,$mon_st,$day_st,$hh_st,$mm_st) = $lb->split_date($cttpos->{$pid}->{itime}); } if($cttpos->{$pid}->{end_time}){ - $cttpos->{$pid}->{end_time} = $now_dt if($node_meta->{ct_table} eq "contenttranspos" && $cttpos->{$pid}->{int10} == 3); + $cttpos->{$pid}->{end_time} = $now_dt if($node_meta->{ct_table} eq "contenttranspos" && $cttpos->{$pid}->{start_time} eq $cttpos->{$pid}->{end_time} ); ($year_en,$mon_en,$day_en,$hh_en,$mm_en) = $lb->split_date($cttpos->{$pid}->{end_time}); }else{ ($year_en,$mon_en,$day_en,$hh_en,$mm_en) = $lb->split_date($cttpos->{$pid}->{itime}); diff --git a/copri4/main/src/Tpl/Liste3.pm b/copri4/main/src/Tpl/Liste3.pm index 59706b7..b76ad5b 100755 --- a/copri4/main/src/Tpl/Liste3.pm +++ b/copri4/main/src/Tpl/Liste3.pm @@ -281,9 +281,10 @@ sub tpl(){ $tplids = "209,218"; } $searchref->{tplids} = "$tplids"; - }elsif($R::detail_search && $R::detail_search eq "search"){ + } + if($R::detail_search && $R::detail_search eq "search"){ $searchref->{offset} = 0; - $searchref->{limit} = 1000; + $searchref->{limit} = 1500; } my $main_ids .= $dbt->collect_noderec($dbh,$main_id); @@ -1118,7 +1119,7 @@ EOF if($cal_count <= 1){ my $scale_color = "#86cbd7;"; my $calement = "calement_86cbd7"; - if($ct4rel->{$id}->{int13} == $cttpos->{$ctid}->{int13} && $cttpos->{$ctid}->{int10} == 7){ + if($ct4rel->{$id}->{int13} == $cttpos->{$ctid}->{int13} && $cttpos->{$ctid}->{int05} == 7){ $scale_color = "#f0536e;"; $calement = "calement_f0536e"; } diff --git a/copri4/main/src/scripts/Ilockit_cloud.pl b/copri4/main/src/scripts/Ilockit_cloud.pl index 83bf9f1..0049c11 100755 --- a/copri4/main/src/scripts/Ilockit_cloud.pl +++ b/copri4/main/src/scripts/Ilockit_cloud.pl @@ -125,8 +125,8 @@ sub utctime { #'deviceTime' => '2021-10-14T08:19:35.000+0000', #'serverTime' => '2021-10-14T07:19:37.000+0000', - #$utc_epoch -= 2*60*60;# -2 std (Sommerzeit) - $utc_epoch -= 1*60*60;# -1 std (Winterzeit) + $utc_epoch -= 2*60*60;# -2 std (Sommerzeit) + #$utc_epoch -= 1*60*60;# -1 std (Winterzeit) $utc_epoch += $latency; $time = gmtime($utc_epoch);#epoch diff --git a/copri4/main/src/scripts/Ilockit_trackingcloud.pl b/copri4/main/src/scripts/Ilockit_trackingcloud.pl index 2f6ac23..5ecfa3e 100755 --- a/copri4/main/src/scripts/Ilockit_trackingcloud.pl +++ b/copri4/main/src/scripts/Ilockit_trackingcloud.pl @@ -87,8 +87,8 @@ sub utctime { my $time = Time::Piece->strptime($date, "%Y-%m-%dT%H:%M:%S"); print FILE "localtime: " . $time->datetime . "\n";#localtime my $utc_epoch = $time->epoch; - #$utc_epoch -= 2*60*60;# -2 std (Sommerzeit) - $utc_epoch -= 1*60*60;# -1 std (Winterzeit) + $utc_epoch -= 2*60*60;# -2 std (Sommerzeit) + #$utc_epoch -= 1*60*60;# -1 std (Winterzeit) $utc_epoch += $latency; $time = gmtime($utc_epoch);#epoch print FILE "utctime: " . $time->datetime . "\n";#utc zulu date time diff --git a/copri4/main/src/scripts/mailTransportcms.pl b/copri4/main/src/scripts/mailTransportcms.pl index 63136ec..2304986 100755 --- a/copri4/main/src/scripts/mailTransportcms.pl +++ b/copri4/main/src/scripts/mailTransportcms.pl @@ -431,7 +431,7 @@ sub send_occupied2hotline { $sendref->{mail_to} = $uadr->{txt08}; my $search = { - table => "contenttranspos", + table_pos => "contenttranspos", int10 => 3, #int33 => 3,#marker for sending 3. SMS int34 => "null",#not staff diff --git a/copri4/main/src/scripts/sms_message.pl b/copri4/main/src/scripts/sms_message.pl index b64a695..fcdacba 100755 --- a/copri4/main/src/scripts/sms_message.pl +++ b/copri4/main/src/scripts/sms_message.pl @@ -61,7 +61,7 @@ $contact_hotline = "Hotline $record_cc->{txt01} $record_cc->{txt08}, $record_cc- if($todo eq "24h_occupied"){ #select booking pos if state=occupied and start_time > 24h my $search = { - table => "contenttranspos", + table_pos => "contenttranspos", int10 => 3, int34 => "null",#if not staff start_time_interval => "(now() - interval '1 day')", diff --git a/copri4/shareeapp-operator/css/local_style20230105.css b/copri4/shareeapp-operator/css/local_style20240315.css similarity index 70% rename from copri4/shareeapp-operator/css/local_style20230105.css rename to copri4/shareeapp-operator/css/local_style20240315.css index 988e6c7..eb54121 100755 --- a/copri4/shareeapp-operator/css/local_style20230105.css +++ b/copri4/shareeapp-operator/css/local_style20240315.css @@ -15,6 +15,43 @@ html,body { text-align: center; } +/* Style the buttons that are used to open and close the accordion panel */ +.accordion { + text-align:left; + padding:0; + background-color: white; + border: none; + cursor: pointer; + text-decoration: none; + outline: none; + transition: 0.4s; +} + +.active, .accordion:hover { + color: #b2acac; +} + +/* Style the accordion panel. Note: hidden by default */ +.panel { + font-weight:normal; + padding:14px 0px 0 4px; + max-height: 0; + transition: max-height 0.5s ease-out; + overflow: hidden; +} + + +#scroll-top-wrapper a:hover { + color: gray; +} +#scroll-top-wrapper { + visibility:visible; + cursor:pointer; + opacity: 1.0; + text-decoration:underline; + padding: 10px; +} + .tdint { padding:0.3em 0.5em; vertical-align: top; diff --git a/copri4/shareeapp-operator/src/Lib/Mlogic.pm b/copri4/shareeapp-operator/src/Lib/Mlogic.pm index 771a5e9..96a7a71 100755 --- a/copri4/shareeapp-operator/src/Lib/Mlogic.pm +++ b/copri4/shareeapp-operator/src/Lib/Mlogic.pm @@ -8,10 +8,11 @@ use warnings; use CGI::Carp qw(fatalsToBrowser); use CGI ':standard'; use Mod::DBtank; - +use Tpl::CalReserv; use Data::Dumper; -my $dbt = new DBtank; +my $dbt = new DBtank; +my $calres = new CalReserv; sub new { my $class = shift; @@ -40,19 +41,11 @@ sub tpl(){ } my $bgcolor1 = $dbt->{primary}->{$varenv->{dbname}}->{bgcolor1}; - if($users_sharee->{c_id} && (!$R::sharee_edit || $R::sharee_edit ne "delete_account2") && ($users_sharee->{c_id} eq $varenv->{superu_id} || $dbt->{copri_conf}->{stage} eq "test" || $users_sharee->{txt08} eq "sigo\@sharee.bike")){ + #show it only in testmode + if($users_sharee->{c_id} && $node_meta->{tpl_id} == 302004 && ($users_sharee->{c_id} eq $varenv->{superu_id} || $dbt->{copri_conf}->{stage} eq "test")){ my $coo = $q->cookie('domcookie') || $q->param('sessionid') || ""; - - #my $api_test = "sharee_fr01"; my $bike="FR1538"; - #my $api_test = "sharee_fr01"; my $bike="FR1005";#E-Lastenrad (bike_group=300101, bike_node=300102) - my $api_test = "sharee_fr01"; my $bike="FR4781";#Tracking and BVB test - #my $api_test = "sharee_kn"; my $bike="KN1011"; - #my $api_test = "sharee_wue"; my $bike="WUE5525"; - #my $api_test = "sharee_sx"; my $bike="S3X1001"; - #my $api_test = "sharee_ren"; my $bike="REN2"; - + my $api_test = "sharee_fr01"; my $bike="FR4781";# test print $q->div({-style=>'float:right;text-align:right;height:25px;padding:6px 15px;background-color:white'},$q->a({-style=>"background-color:#ffffff;color:#$bgcolor1;", -href=>"$varenv->{metahost}/src/scripts/tests/index.pl?sessionid=$coo\&api_test=$api_test\&bike=$bike\&user_test=$users_sharee->{txt08}", -target=>'_blank'}," [ tests --> $api_test ] "),"$users_sharee->{txt08}",$q->a({-style=>"color:#$bgcolor1;", -href=>"logout_sharee$session"},"logout")),"\n"; - } print "
\n"; @@ -60,8 +53,6 @@ sub tpl(){ $self->tplselect($q,$node_meta,$users_dms,$mode,$varenv,$users_sharee,$feedb); print "
\n"; print "\n"; - #print "\n"; - } #2021-05-05 changed to Mlogic @@ -76,30 +67,36 @@ sub tplselect(){ my $feedb = shift || ""; $q->import_names('R'); - my $sort = ""; - my $lang = "de"; - my $tpl_id = $node_meta->{tpl_id}; if($node_meta->{main_id}){ - if($tpl_id == 2){ + if($node_meta->{tpl_id} == 2){ require "Tpl/Anmelden.pm"; &Anmelden::tpl($node_meta,$users_dms,$mode,$varenv,$users_sharee,$feedb); - }elsif($tpl_id == 302 || $tpl_id == 302008){ + }elsif($node_meta->{tpl_id} == 302 || $node_meta->{tpl_id} == 302008){ require "Tpl/FormEdit.pm"; &FormEdit::tpl($node_meta,$users_dms,$mode,$varenv,$users_sharee,$feedb); - }elsif($tpl_id == 302004){ + }elsif($node_meta->{tpl_id} == 302004){ require "Tpl/RentalData.pm"; &RentalData::tpl($node_meta,$users_dms,$varenv,$users_sharee,$feedb); - }elsif($tpl_id == 308){ + }elsif($node_meta->{tpl_id} == 308){ require "Tpl/PayoneSelect.pm"; &PayoneSelect::tpl($q,$node_meta,$users_dms,$varenv,$users_sharee,$feedb); - }elsif($tpl_id == 197){ + }elsif($node_meta->{tpl_id} == 314){ + #CalendarReserv CalReserv (ex. MapReserv_v2) + $calres->tpl($q,$node_meta,$users_dms,$varenv,$users_sharee,$feedb); + #}elsif($node_meta->{tpl_id} == 315){ + #CalendarBikes CalReserv iframe + #$calres->tpl($q,$node_meta,$users_dms,$varenv,$users_sharee,$feedb); + }elsif($node_meta->{tpl_id} == 197){ require "Tpl/Contact.pm"; &Contact::tpl($node_meta,$users_dms,$mode,$varenv,$users_sharee,$feedb); } + +print ""; + } - my $debug = "Mlogic --> (users_sharee->{c_id}: $users_sharee->{c_id} | ct_table: $node_meta->{ct_table} | parent_id: $node_meta->{parent_id} | main_id: $node_meta->{main_id} | tpl_id: $node_meta->{tpl_id} | u_id: $users_dms->{u_id} | mode: $mode)"; - print $q->div({-style=>'position:fixed;bottom:0%;right:2%;z-index:10;font-size:13px;'},"$debug"),"\n" if($users_sharee->{c_id} eq $varenv->{superu_id}); + my $debug = "Mlogic --> (users_sharee->{c_id}: $users_sharee->{c_id} | ct_table: $node_meta->{ct_table} | parent_id: $node_meta->{parent_id} | main_id: $node_meta->{main_id} | tpl_id: $node_meta->{tpl_id})"; + print $q->div({-style=>'position:fixed;bottom:0%;right:2%;z-index:10;font-size:13px;'},"$debug"),"\n" if($users_sharee->{c_id} eq $varenv->{superu_id} || $dbt->{copri_conf}->{stage} eq "test"); } diff --git a/copri4/shareeapp-operator/src/Tpl/AccountSubmenu.pm b/copri4/shareeapp-operator/src/Tpl/AccountSubmenu.pm index 0c3f2c9..bc0a799 100755 --- a/copri4/shareeapp-operator/src/Tpl/AccountSubmenu.pm +++ b/copri4/shareeapp-operator/src/Tpl/AccountSubmenu.pm @@ -134,12 +134,14 @@ if(1==1){ my $mstyle_1_5=""; my $mstyle_2=""; my $mstyle_3=""; + my $mstyle_4=""; if($node_meta->{main_id} == $node1->{$id1}->{main_id}){ $mstyle_1 .= "background-color: #$hgcolor1;" if("$node1->{$id1}->{node_name}" eq "$varenv->{accounting_1}"); $mstyle_1_5 .= "background-color: #$hgcolor1;" if("$node1->{$id1}->{node_name}" eq "$varenv->{accounting_1_5}"); $mstyle_2 .= "background-color: #$hgcolor1;" if("$node1->{$id1}->{node_name}" eq "$varenv->{accounting_2}"); $mstyle_3 .= "background-color: #$hgcolor1;" if("$node1->{$id1}->{node_name}" eq "$varenv->{accounting_3}"); + $mstyle_4 .= "background-color: #$hgcolor1;" if("$node1->{$id1}->{node_name}" eq "$varenv->{accounting_4}"); #sharee AGB if(!$users_sharee->{int14}){ @@ -154,6 +156,10 @@ if(1==1){ print $q->li($q->a({-style=>"$mstyle_1_5",-title=>"$varenv->{accounting_1_5}", -href=>"/$viewsel[0]/Account/$varenv->{accounting_1_5}$session"}, $q->img({-src=>"$varenv->{metahost}/img/Account_Zahlungsart.svg"}))),"\n"; print $q->li($q->a({-style=>"$mstyle_2",-title=>"$varenv->{accounting_2}", -href=>"/$viewsel[0]/Account/$varenv->{accounting_2}$session"}, $q->img({-src=>"$varenv->{metahost}/img/Account_Kontoverbindung.svg"}))),"\n"; print $q->li($q->a({-style=>"$mstyle_3",-title=>"$varenv->{accounting_3}", -href=>"/$viewsel[0]/Account/$varenv->{accounting_3}$session"}, $q->img({-src=>"$varenv->{metahost}/img/Account_Verleihdaten.svg"}))),"\n"; + #Calendar Reservation beta + if($users_sharee->{c_id} && $dbt->{copri_conf}->{betau_id}->{$users_sharee->{c_id}}){ + print $q->li($q->a({-style=>"$mstyle_4",-title=>"$varenv->{accounting_4}", -href=>"/$viewsel[0]/Account/$varenv->{accounting_4}$session"}, $q->span({-class=>"bi bi-calendar3", -style=>"font-size: 2rem;width:3rem;padding-top:0.4rem;"}))),"\n"; + } } else{ print $q->li($q->a({-style=>"$mstyle_1",-title=>"$varenv->{accounting_1}", -href=>"/$viewsel[0]/Account/$varenv->{accounting_1}$session"}, $q->img({-src=>"$varenv->{metahost}/img/Account_Kundendaten.svg"}))),"\n"; diff --git a/copri4/shareeapp-operator/src/Tpl/CalReserv.pm b/copri4/shareeapp-operator/src/Tpl/CalReserv.pm new file mode 100755 index 0000000..f8cf1b8 --- /dev/null +++ b/copri4/shareeapp-operator/src/Tpl/CalReserv.pm @@ -0,0 +1,634 @@ +package CalReserv; +# +# SPDX-License-Identifier: AGPL-3.0-or-later +# Copyright (c) Rainer Gümpelein, TeilRad GmbH +# +#Bike calendar-reservation +# +use strict; +use warnings; +use POSIX; +use CGI ':standard'; +use Scalar::Util qw(looks_like_number); +use JSON; +use DateTime; +use DateTime::Format::Strptime; +use DateTime::Format::Pg; +use LWP::UserAgent; +use Mod::Basework; +use Mod::DBtank; +use Mod::Buttons; +use Tpl::AccountSubmenu; +use Data::Dumper; + +sub new { + my $class = shift; + my $self = {}; + bless($self,$class); + return $self; +} + +sub tpl { + my $self = shift; + my $q = shift; + my $node_meta = shift; + my $users_dms = shift || ""; + my $varenv = shift; + my $users_sharee = shift || ""; + my $feedb = shift || ""; + + my $bw = new Basework; + my $dbt = new DBtank; + my $but = new Buttons; + my $submenu = new AccountSubmenu; + my $path = $q->path_info(); + my $dbh = ""; + my $red = "#c83434"; + + my $coo = $q->cookie(-name=>'domcookie') || $R::sessionid; + my $session=""; + my $session_and=""; + if($R::sessionid && length($R::sessionid) > 20 && !$q->cookie(-name=>'domcookie')){ + $session = "?sessionid=$R::sessionid"; + $session_and = "&sessionid=$R::sessionid"; + } + my $bike = $q->escapeHTML($R::bike) || ""; + my $bgcolor1 = "009899";#sharee + $bgcolor1 = $dbt->{website}->{$varenv->{syshost}}->{bgcolor1} if($dbt->{website}->{$varenv->{syshost}}->{bgcolor1}); + $bgcolor1 = $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{bgcolor1} if($dbt->{merchant_ids}->{$varenv->{merchant_id}}->{bgcolor1}); + my $initMap = "48.741246, 11.210390"; + my $map_zoom = 7; + my $project = "all"; + my $uri_server = $dbt->{primary}->{sharee_primary}->{primaryApp}; + + my $timestamp = DateTime->now( time_zone => "Europe/Berlin" ); + my $dt0 = DateTime->now( time_zone => "Europe/Berlin" ); + my $dt1 = DateTime->now( time_zone => "Europe/Berlin" ); + my $strp = DateTime::Format::Strptime->new( + pattern => '%Y-%m-%dT%H:%M', + locale => 'de_DE', + time_zone => 'Europe/Berlin', + on_error => 'croak', + ); + + my $reserv_starttime = $R::reserv_starttime || ""; + my $reserv_endtime = $R::reserv_endtime || ""; + + if($reserv_starttime && $reserv_starttime =~ /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/){ + $dt0 = $strp->parse_datetime($reserv_starttime); + $reserv_starttime = $dt0->datetime; + } + if($reserv_endtime && $reserv_endtime =~ /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/){ + $dt1 = $strp->parse_datetime($reserv_endtime); + $reserv_endtime = $dt1->datetime; + } + + if($dt0 < $timestamp){ + $dt0 = $strp->parse_datetime($timestamp); + $reserv_starttime = $dt0->datetime; + $reserv_starttime =~ s/:00$//; + $dt1 = $strp->parse_datetime($timestamp); + $dt1->add( hours => 4); + $reserv_endtime = $dt1->datetime; + $reserv_endtime =~ s/:00$//; + } + + if(!$reserv_starttime || $reserv_starttime !~ /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/){ + $dt0 = $strp->parse_datetime($timestamp); + $reserv_starttime = $dt0->datetime; + $reserv_starttime =~ s/:00$//; + } + + if(!$reserv_endtime || $reserv_endtime !~ /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/){ + $dt1 = $strp->parse_datetime($timestamp); + $dt1->add( hours => 3); + $reserv_endtime = $dt1->datetime; + $reserv_endtime =~ s/:00$//; + } + + print "
\n"; + + #subMenue-------- + $submenu->tpl($node_meta,$users_dms,$varenv,$users_sharee,$feedb); + #----------------- + + print $q->start_form(-name=>'calreservscreen', -action=>""),"\n"; + print $q->hidden(-name=>"sessionid",-override=>1,-value=>"$R::sessionid") if($R::sessionid); + print $q->hidden(-name=>"calreserv",-override=>1,-value=>"1");#to get uri_operator by GBFSout + + + #Station select by map + my $icon_green = "Open_Green.png"; + my $icon_red = "Open_Red.png"; + my $icon_blue = "Open_Blue.png"; + $initMap =~ s/\s//g; + my ($lat,$lng) = split(/,/,$initMap); + if($R::select_station && $R::select_station =~ /LatLng\((\d+\.\d+),\s(\d+\.\d+)\)/){ + $lat = $1; + $lng = $2; + } + +print< + + + + + +EOF +; + +print $q->div({-class=>'content_title3',-style=>''}, "$varenv->{cms}->{'iframe-calendar-reserv-intro'}->{txt}"),"\n"; +#print $q->div({-style=>'padding:10px 0;'},"Mietrad Reservierung. Radstation in Karte auswählen, Fahrtbeginn und Fahrtende einstellen und verfügbares Mietrad buchen."),"\n"; +print $q->div({-id=>"geolocatestate"},""),"\n"; + +print "
\n"; + + #print $q->div({-style=>'padding:15px 0;'},$q->b("Mietradstation: "),$q->span({-id=>"station_selected"},"")),"\n"; + #with Station select $stations_json + my $list_options = ""; + my %gbfs_station = (); + my %selected_station = (); + if(1==1){ + my $rest_stations = "request=stations_available&calreserv=1&authcookie=$coo"; + my $stations_json = fetchserver_json("",$uri_server,$rest_stations); + eval { + my $response_stations = {}; + $response_stations = decode_json($stations_json); + + foreach my $station (sort {$response_stations->{shareejson}->{stations}->{$a}->{station} cmp $response_stations->{shareejson}->{stations}->{$b}->{station} } keys (%{ $response_stations->{shareejson}->{stations} })) { + #print Dumper($response_stations->{shareejson}->{stations}->{$station}); + $response_stations->{shareejson}->{stations}->{$station}->{gps}->{latitude} =~ s/0$//g; + $response_stations->{shareejson}->{stations}->{$station}->{gps}->{longitude} =~ s/0$//g; + $gbfs_station{$station}{LatLng} = "LatLng($response_stations->{shareejson}->{stations}->{$station}->{gps}->{latitude}, $response_stations->{shareejson}->{stations}->{$station}->{gps}->{longitude})"; + $gbfs_station{$station}{name} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$response_stations->{shareejson}->{stations}->{$station}->{description})); + $gbfs_station{$station}{station_id} = $response_stations->{shareejson}->{stations}->{$station}->{station}; + if($R::select_station && $R::select_station eq $gbfs_station{$station}{LatLng}){ + $selected_station{uri_operator} = $response_stations->{shareejson}->{stations}->{$station}->{uri_operator}; + $selected_station{name} = $gbfs_station{$station}{name}; + $selected_station{station_id} = $gbfs_station{$station}{station_id}; + $list_options .= "\n"; + }else{ + $list_options .= "\n"; + } + } + }; + if ($@){ + $bw->log("Failure, CalendarReserv station_information not valid","",""); + warn $@; + } + + print $q->label({-for=>'select_station', -class=>'form-label'},"Mietradstation"),"\n"; + print "
\n"; + #print $q->span({-class=>"input-group-text bi bi-record-circle", -style=>"font-size: 1.5rem;width:3rem;"},""),"\n"; + #print $q->input({-id=>'select_station', -name=>'select_station', -type=>'text', -list=>'list-stations', -class=>'form-control', -style=>'max-width:500px;font-weight:bold;', -placeholder=>'Ort oder Stationname', -override=>1},""),"\n"; + print ""; + #print $q->input({-type=>'reset',-value=>'Reset'},""),"\n"; + print "
\n"; + } + #end with Station select $stations_json + +print ""; + +print< + //document.getElementById('select_station').value = 'LatLng(47.976634, 7.825490)'; + + var map = L.map('map', { scrollWheelZoom: false }).setView([$lat, $lng], $map_zoom); + + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' +}).addTo(map); + +var icon_green = L.icon({ + iconUrl: '$varenv->{metahost}/img/$icon_green', + iconSize: [37, 37], + iconAnchor: [20, 37], + popupAnchor: [-2, -36] + //shadowUrl: 'marker-shadow.png', + //shadowSize: [68, 95], + //shadowAnchor: [22, 94] +}); +var icon_red = L.icon({ + iconUrl: '$varenv->{metahost}/img/$icon_red', + iconSize: [37, 37], + iconAnchor: [20, 37], + popupAnchor: [-2, -36] +}); + +//Only stations with bike_count +Promise.all([ + fetch( + "$uri_server/GBFSout?request=stations_available&calreserv=1&authcookie=$coo" + )]).then(async ([response1]) => { + const responseData1 = await response1.json(); + + const data1 = responseData1.data.stations; + + const layerGroup = L.featureGroup().addTo(map); + data1.forEach(({ lat, lon, name, bike_count, uri_operator, station_id: stationId }) => { + console.log('Station: ' + stationId , name, bike_count); + + layerGroup.addLayer( + //L.marker([lat, lon], { icon:icon_green }).bindPopup(`Station: \${name} \${stationId}
\${lat},\${lon}`).on('click', clickedGPS) + L.marker([lat, lon], { icon:icon_green }).bindPopup(`Station \${name} \${stationId}`).on('click', clickedGPS) + ); + + }); + + //disabled to setView on current location + //map.fitBounds(layerGroup.getBounds()); +}); + +function clickedGPS(e) { + const select_station = document.querySelector('#select_station'); + select_station.value = e.latlng + //station_selected.textContent = 'FR101' + console.log('clickedGPS:' + select_station.value); +} + +function onLocationFound(e) { + console.log('onLocationFound:' + e.latlng); + const geolocatestate = document.querySelector('#geolocatestate'); + var radius = e.accuracy; + + //L.marker(e.latlng).addTo(map).bindPopup("You are within " + radius + " meters from this point").openPopup(); + L.circle(e.latlng, radius).addTo(map); + geolocatestate.textContent = 'Stationen in Umgebung'; +} + + +function onLocationError(e) { + alert(e.message); +} + +function lastLocation() { + var latlng = L.latLng($lat, $lng); + console.log('lastLocation:' + latlng); + const geolocatestate = document.querySelector('#geolocatestate'); + var radius = 5000; + + L.marker(latlng, { icon:icon_green }).addTo(map).bindPopup(`Station $selected_station{name} | $selected_station{station_id}`).openPopup(); + L.circle(latlng, radius).addTo(map); + geolocatestate.textContent = 'Station nach Auswahl'; +} + + +if("$R::select_station"){ + map.on('locationfound', lastLocation); + map.locate({setView: false, maxZoom: 16}); + map.setView(L.latLng($lat, $lng), 11); +}else{ + map.on('locationfound', onLocationFound); + map.on('locationerror', onLocationError); + map.locate({setView: true, maxZoom: 16}); +} + + +EOF +; + + #end Station select by map + + #if(!$bike){ + print "
\n"; + print $q->label({-for=>'reserv_starttime', -class=>'form-label'},"Fahrtbeginn"),"\n"; + print $q->input({-id=>'reserv_starttime', -name=>'reserv_starttime',-type=>'datetime-local', -class=>'form-control', -style=>'max-width:230px;', -value=>"$reserv_starttime", -override=>1},""),"\n"; + print $q->label({-for=>'reserv_endtime', -class=>'form-label', -style=>'padding-top:1em;'},"Fahrtende"),"\n"; + print $q->input({-id=>'reserv_endtime', -name=>'reserv_endtime',-type=>'datetime-local', -class=>'form-control', -style=>'max-width:230px;', -value=>"$reserv_endtime", override=>1},""),"\n"; + print "
\n"; + #} + + if(1==2){ + print $q->div({-class=>"accordion bi bi-caret-down"}, "mehr Filter anzeigen"),"\n"; + print "
\n"; + + print "
\n"; + my $ecargo_checked = "checked"; + $ecargo_checked = "" if($R::sharee_edit && !$R::ecargo); + print "\n"; + print $q->label({-class=>"form-check-label", -for=>"ecargo",-style=>'padding-top:5px;'},"E-Lastenrad"),"\n"; + print "
\n"; + print "
\n"; + my $cargo_checked = "checked"; + $cargo_checked = "" if($R::sharee_edit && !$R::cargo); + print "\n"; + print $q->label({-class=>"form-check-label", -for=>"cargo",-style=>'padding-top:5px;'},"Lastenrad"),"\n"; + print "
\n"; + print "
\n"; + my $city_checked = "checked"; + $city_checked = "" if($R::sharee_edit && !$R::city); + print "\n"; + print $q->label({-class=>"form-check-label", -for=>"city",-style=>'padding-top:5px;'},"Stadtrad"),"\n"; + print "
\n"; + + print "
\n"; + } + + if($R::sharee_edit =~ /calendar_bikes_available/ && $bike){ + print $q->div({-style=>'margin:1em 0;text-align:center;clear:both;'},""),"\n"; + print $q->hidden(-name=>"bike",-override=>1,-value=>"$bike"); + } + my $but_search = "Suchen"; + $but_search = "Erneut suchen" if($R::sharee_edit =~ /calendar_bikes_available/); + print $q->div({-style=>'margin:1em 0;text-align:center;clear:both;'},""),"\n"; + + print $q->div({-id=>'reserved_bikes'},""),"\n";#not used + + #$bikes_json + if($R::sharee_edit =~ /calendar_bikes_available/){ + + my $rest_bikes = "request=bikes_available&calreserv=1&reserv_starttime=$R::reserv_starttime&reserv_endtime=$R::reserv_endtime&authcookie=$coo&lang=de"; + $rest_bikes .= "&station=$selected_station{station_id}" if($selected_station{station_id}); + + if($R::select_station && $R::select_station =~/LatLng\((\d+\.\d+), (\d+\.\d+)\)/){ + my $Lat = $1; + my $Lng = $2; + $rest_bikes .= "&Lat=$Lat&Lng=$Lng"; + $uri_server = $selected_station{uri_operator} if($selected_station{uri_operator}); + } + my $list_title = "Mieträder an Station:"; + if($R::sharee_edit ne "calendar_bikes_available_all" && $bike){ + $list_title = "Mietrad an Station:"; + $rest_bikes .= "&bike=$bike"; + } + + my $bikes_json = fetchserver_json("",$uri_server,$rest_bikes); + eval { + my $response_bikes = {}; + $response_bikes = decode_json($bikes_json); + + #bikes available + print $q->div({-class=>'content_title2',-style=>''},"$list_title $selected_station{name} | $selected_station{station_id}"),"\n" if(1 == 1); + foreach my $bike (sort {$response_bikes->{shareejson}->{bikes}->{$a}->{bike} cmp $response_bikes->{shareejson}->{bikes}->{$b}->{bike} } keys (%{ $response_bikes->{shareejson}->{bikes} })) { + + #print "
\n"; + print $q->div({-style=>'padding:0.1em 0;margin:0.5em 0;background-color:#b6b6b6;'},""),"\n"; + my $bike_image = "bike_Cargo_SoleHumanPowered_Two.png"; + $bike_image = "bike_Cargo_SoleHumanPowered_Trike.png" if($response_bikes->{shareejson}->{bikes}->{$bike}->{bike_type}->{category} eq "cargo" && $response_bikes->{shareejson}->{bikes}->{$bike}->{bike_type}->{wheels} eq "3"); + $bike_image = "bike_Cargo_Pedelec_Two.png" if($response_bikes->{shareejson}->{bikes}->{$bike}->{bike_type}->{category} eq "cargo" && $response_bikes->{shareejson}->{bikes}->{$bike}->{bike_type}->{engine}); + $bike_image = "bike_City_SoleHumanPowered_Two.png" if($response_bikes->{shareejson}->{bikes}->{$bike}->{bike_type}->{category} eq "city"); + + print $q->div({-style=>'padding:0.5em;float:left;'},$q->img({-style=>'width:100px;', -src=>"$varenv->{metahost}/img/$bike_image"})),"\n"; + print $q->div({-style=>'padding:0.5em;'},$q->span({-style=>'font-weight:bold;'},"$response_bikes->{shareejson}->{bikes}->{$bike}->{description} "),"$response_bikes->{shareejson}->{bikes}->{$bike}->{bike}"),"\n"; + + my $dts = $strp->parse_datetime($reserv_starttime); + my $start_loc = $dts->strftime("%d.%m.%Y %H:%M"); + my $dte = $strp->parse_datetime($reserv_endtime); + my $end_loc = $dte->strftime("%d.%m.%Y %H:%M"); + print $q->div({-style=>''},"Fahrtbeginn: $start_loc"),"\n"; + print $q->div({-style=>''},"Fahrtende: $end_loc"),"\n"; + + print $q->div({-id=>"return_state_$bike",-style=>'color:green;'},""),"\n"; + + #collect timerange + my $set_starttime = ""; + my $set_endtime = ""; + my $j = 0; + my $dt2 = DateTime->now(time_zone => "Europe/Berlin"); + my $dt3 = DateTime->now(time_zone => "Europe/Berlin"); + my $dtnow = $strp->parse_datetime($timestamp); + $dtnow->add( minutes => 1); + $set_starttime = $dtnow->datetime; + + my %blockedhash = (); + my %reservedhash = (); + my $sb = 100;#start blockedhash index . 1 + my $eb = 100;#end blockedhash index . 2 + my $sr = 100;#start reservedhash index . 1 + my $er = 100;#end reservedhash index . 2 + $blockedhash{$sb . '1'} = $set_starttime; + foreach my $rid (sort {$response_bikes->{shareejson}->{bikes}->{$bike}->{blocked}->{$a}->{start_time} cmp $response_bikes->{shareejson}->{bikes}->{$bike}->{blocked}->{$b}->{start_time} } keys (%{ $response_bikes->{shareejson}->{bikes}->{$bike}->{blocked} })) { + $j++; + $dt2 = DateTime::Format::Pg->parse_datetime($response_bikes->{shareejson}->{bikes}->{$bike}->{blocked}->{$rid}->{start_time}); + $sr++; + $er++; + + if($j==1){ + $dt3 = DateTime::Format::Pg->parse_datetime($response_bikes->{shareejson}->{bikes}->{$bike}->{blocked}->{$rid}->{end_time}); + } + + if($j==1 && $dtnow < $dt3){ + $set_endtime = $dt2->datetime; + $reservedhash{$sr . '1'} = $set_endtime;#reserv start_time + $reservedhash{$er . '2'} = $set_starttime;#reserv end_time + $dt3->add( minutes => 15); + $set_starttime = $dt3->datetime; + $blockedhash{$sb . '1'} = $set_starttime; + }else{ + my $dt0 = DateTime::Format::Pg->parse_datetime($response_bikes->{shareejson}->{bikes}->{$bike}->{blocked}->{$rid}->{start_time}); + my $dtend = $strp->parse_datetime($dt0); + $set_endtime = $dtend->datetime; + $reservedhash{$sr . '1'} = $set_endtime;#reserv start_time + $blockedhash{$eb . '2'} = $set_endtime;#blocked end_time + + my $dt1 = DateTime::Format::Pg->parse_datetime($response_bikes->{shareejson}->{bikes}->{$bike}->{blocked}->{$rid}->{end_time}); + my $dtstart = $strp->parse_datetime($dt1); + $set_starttime = $dtstart->datetime; + $reservedhash{$er . '2'} = $set_starttime;#reserv end_time + + $sb++; + $eb++; + $dt1->add( minutes => 15); + $dtstart = $strp->parse_datetime($dt1); + $set_starttime = $dtstart->datetime; + $blockedhash{$sb . '1'} = $set_starttime;#blocked start_time + } + } + $dtnow->add( weeks => 4); + $set_endtime = $dtnow->datetime; + $blockedhash{$eb . '2'} = $set_endtime; + #print Dumper(\%reservedhash) . "
\n"; + #print Dumper(\%blockedhash) . "
\n"; + #end collect timerange + + #view red flag if bike not available on selected rental timerange + my $reservindex = 0; + my $se = 0; + my $reservbut = 0; + foreach my $ri (sort keys %reservedhash){ + if($ri =~ /(\d{3})(\d{1})/){ + $reservindex = $1; + $se = $2; + } + if($ri =~ /^$reservindex/ && $se == 1){ + my $dtx = $strp->parse_datetime($reservedhash{$ri}); + my $end_ri = $ri + 1; + my $dty = $strp->parse_datetime($reservedhash{$end_ri}); + if($dty >= $dt0 && $dty <= $dt1 && $dtx <= $dt1){ + $reservbut = 1; + #print $q->div({-style=>'color:red;'},"Im gewähltem Zeitfenster nicht verfügbar"),"\n"; + #print "$ri Von: $reservedhash{$ri}
\n"; + #print "$end_ri Bis: $reservedhash{$end_ri}
\n"; + } + } + } + + #delete blockedhash with too small ranges + my $rangeindex = 0; + my $se = 0; + foreach my $ri (sort keys %blockedhash){ + if($ri =~ /(\d{3})(\d{1})/){ + $rangeindex = $1; + $se = $2; + } + if($ri =~ /^$rangeindex/ && $se == 1){ + my $dtx = $strp->parse_datetime($blockedhash{$ri}); + my $end_ri = $ri + 1; + my $dty = $strp->parse_datetime($blockedhash{$end_ri}); + if($dty <= $dtx){ + delete $blockedhash{$ri}; + delete $blockedhash{$end_ri}; + } + } + } + + my $availability = ""; + my $href = ""; + #build availability links + foreach my $ri (sort keys %blockedhash){ + if($ri =~ /(\d{3})(\d{1})/){ + $rangeindex = $1; + $se = $2; + } + if($ri =~ /^$rangeindex/ && $se == 1){ + $href = "/app/Account/CalendarReserv?sharee_edit=calendar_bikes_available&select_station=$R::select_station&bike=$bike&calreserv=1&authcookie=$coo&lang=de"; + #print "$ri Von: $blockedhash{$ri}
\n"; + my $dtx = $strp->parse_datetime($blockedhash{$ri}); + my $start_loc = $dtx->strftime("%d.%m.%Y %H:%M"); + $href .= "&reserv_starttime=$blockedhash{$ri}"; + $availability .= "
Von: $start_loc
\n"; + } + if($ri =~ /^$rangeindex/ && $se == 2){ + #print "$ri Bis: $blockedhash{$ri}
---
\n"; + my $dty = $strp->parse_datetime($blockedhash{$ri}); + my $end_loc = $dty->strftime("%d.%m.%Y %H:%M"); + $href .= "&reserv_endtime=$blockedhash{$ri}"; + $availability .= "
Zeitfenster übernehmen
\n +
Bis: $end_loc
\n +
\n"; + } + } + + +print < + +EOF +; + + if($reservbut){ + print $q->div({-style=>'color:red;'},"Im gewähltem Zeitfenster nicht verfügbar"),"\n"; + }else{ + #Mietrad buchen + print $q->div({-id=>"button_reserv_$bike",-style=>'clear:both;text-align:center;display:block;'},"Mietrad buchen"),"\n"; + + #Buchung stornieren + print $q->div({-id=>"button_cancel_$bike",-style=>'clear:both;text-align:center;display:none;'},"Buchung stornieren"),"\n"; + } + + #Weitere Verfügbarkeit anzeigen + print $q->div({-id=>"button_availablbility_$bike",-style=>'clear:both;text-align:center;display:block;'},"Weitere Verfügbarkeit anzeigen"),"\n"; + + + #print Dumper($response_bikes->{shareejson}->{bikes}->{$bike}->{rental_description}->{tarif_elements}); + foreach my $ele (%{ $response_bikes->{shareejson}->{bikes}->{$bike}->{rental_description}->{tarif_elements} }){ + if($response_bikes->{shareejson}->{bikes}->{$bike}->{rental_description}->{tarif_elements}->{$ele}[0] && $response_bikes->{shareejson}->{bikes}->{$bike}->{rental_description}->{tarif_elements}->{$ele}[1]){ + print $q->div({-style=>'padding:0.2em 0.5em;'},"$response_bikes->{shareejson}->{bikes}->{$bike}->{rental_description}->{tarif_elements}->{$ele}[0] : $response_bikes->{shareejson}->{bikes}->{$bike}->{rental_description}->{tarif_elements}->{$ele}[1]"),"\n"; + } + } + + #print "
\n"; + } + + #bikes_occupied + print $q->div({-style=>'padding:0.1em 0;margin:0.5em 0;background-color:#b6b6b6;'},""),"\n"; + my $i = 0; + foreach my $rid (sort {$response_bikes->{shareejson}->{bikes_occupied}->{$a}->{start_time} cmp $response_bikes->{shareejson}->{bikes_occupied}->{$b}->{start_time} } keys (%{ $response_bikes->{shareejson}->{bikes_occupied} })) { + my $reserv_starttime = DateTime::Format::Pg->parse_datetime($response_bikes->{shareejson}->{bikes_occupied}->{$rid}->{start_time}); + my $reserv_endtime = DateTime::Format::Pg->parse_datetime($response_bikes->{shareejson}->{bikes_occupied}->{$rid}->{end_time}); + my $start_loc = $reserv_starttime->strftime("%d.%m.%Y %H:%M"); + my $end_loc = $reserv_endtime->strftime("%d.%m.%Y %H:%M"); + $i++; + my $oprefix = ""; + $oprefix = $1 if($response_bikes->{shareejson}->{bikes_occupied}->{$rid}->{station} =~ /([A-Z]+)/i); + my $bike = $response_bikes->{shareejson}->{bikes_occupied}->{$rid}->{bike}; + print $q->div({-style=>'padding:1em 0.5em;font-weight:bold;'},"Deine $oprefix Buchungen:"),"\n" if($i == 1); + #selector by $rid pos_id + print $q->div({-id=>"return_state_$rid"},""),"\n"; + print $q->div({-id=>"button_cancel_$rid", -style=>'padding:0.2em 0.5em;color:green;display:block;'},"Buchung stornieren $start_loc - $end_loc: $response_bikes->{shareejson}->{bikes_occupied}->{$rid}->{description} $bike an Station $response_bikes->{shareejson}->{bikes_occupied}->{$rid}->{station}"),"\n"; + print $q->div({-id=>"button_reserv_$rid",-style=>'color:red;'},""),"\n";#dummy + } + + }; + if ($@){ + $bw->log("Failure, CalendarReserv bike_json not valid","",""); + warn $@; + } + }#end $bikes_json + + + + print $q->end_form,"\n"; + print $q->div({-id=>'scroll-top-wrapper'},"nach oben"),"\n" if($R::sharee_edit =~ /calendar_bikes_available/); + + print $q->div({-style=>'position:fixed;bottom:2%;right:2%;z-index:10;font-size:13px;'},"--> $varenv->{syshost} | $varenv->{merchant_id} | $bgcolor1 | template -> $node_meta->{tpl_name},$node_meta->{tpl_id}"),"\n" if($users_sharee->{c_id} eq $dbt->{copri_conf}->{superu_id} || $dbt->{copri_conf}->{stage} eq "test"); + + print "
\n"; +} + +#requestor +sub fetchserver_json { + my $self = shift; + my $uri_server = shift || ""; + my $rest = shift || ""; + my $server_request = "$uri_server/APIjsonserver?$rest"; + + my $ua = LWP::UserAgent->new; + $ua->agent("sharee CalReserv"); + + my $req = HTTP::Request->new(GET => "$server_request"); + $req->content_type('application/x-www-form-urlencoded'); + $req->content($rest); + + #Pass request to the user agent and get a response back + my $res = $ua->request($req); + #SSL certificate must be valid + #print Dumper($res); + # Check the outcome of the response + if ($res->is_success) { + #print $res->content; + return $res->content; + #print $res->status_line, "\n"; + }else { + return ""; + #print $res->status_line, "\n"; + } +} + +1; diff --git a/copri4/shareeapp-operator/src/Tpl/FormEdit.pm b/copri4/shareeapp-operator/src/Tpl/FormEdit.pm index a7fabb4..3e308b2 100755 --- a/copri4/shareeapp-operator/src/Tpl/FormEdit.pm +++ b/copri4/shareeapp-operator/src/Tpl/FormEdit.pm @@ -335,7 +335,7 @@ EOF print $q->div(" "); foreach my $opid (keys(%$ctadrcoupon)){ if($ctadrcoupon->{$opid}->{txt15}){ - print $q->div("$bonus_saved $ctadrcoupon->{$opid}->{oprefix}-$ctadrcoupon->{$opid}->{txt15}"),"\n"; + print $q->div("$bonus_saved $ctadrcoupon->{$opid}->{oprefix} $ctadrcoupon->{$opid}->{txt15}"),"\n"; } } diff --git a/copri4/shareeconf/examples/sharee_operator.sql.gz b/copri4/shareeconf/examples/sharee_operator.sql.gz index 5481a07..8d7ef0d 100755 Binary files a/copri4/shareeconf/examples/sharee_operator.sql.gz and b/copri4/shareeconf/examples/sharee_operator.sql.gz differ diff --git a/copri4/shareeweb-project/src/Lib/Config.pm b/copri4/shareeweb-project/src/Lib/Config.pm index aac6159..8c9ba4a 100755 --- a/copri4/shareeweb-project/src/Lib/Config.pm +++ b/copri4/shareeweb-project/src/Lib/Config.pm @@ -45,6 +45,7 @@ sub envonline(){ accounting_1_5 => $globalconf{shareeapp_conf}->{accounting_1_5}, accounting_2 => $globalconf{shareeapp_conf}->{accounting_2}, accounting_3 => $globalconf{shareeapp_conf}->{accounting_3}, + accounting_4 => $globalconf{shareeapp_conf}->{accounting_4}, superu_id => $globalconf{copri_conf}->{superu_id}, debug => $globalconf{copri_conf}->{debug}, logdir => $globalconf{copri_conf}->{logdir},