package APIfunc; # # SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (c) Rainer Gümpelein, TeilRad GmbH # #Server methods for sharee API # #perl -cw #use lib qw(/var/www/copri-bike/shareeapp-operator/src); # use strict; use warnings; use POSIX; use CGI; # only for debugging use Digest::MD5 qw(md5 md5_hex); use Scalar::Util qw(looks_like_number); use DateTime; use DateTime::Format::Pg; use URI::Encode; use Config::General; use Lib::Config; use Mod::Libenz; use Mod::DBtank; use Mod::Callib; use Mod::Basework; use Mod::Pricing; #use Mod::APIsigclient;#no! use Data::Dumper; use Sys::Hostname; my $hostname = hostname; my $cf = new Config; my $lb = new Libenz; my $dbt = new DBtank; my $cal = new Callib; my $bw = new Basework; my $pri = new Pricing; #my $si = new APIsigclient; sub new { my $class = shift; my $self = {}; bless($self,$class); return $self; } my $now_dt = strftime "%Y-%m-%d %H:%M:%S", localtime; my $now_date = strftime "%Y-%m-%d", localtime; my $lang="de"; my $owner=188;#via API my $dbh = ""; #fetch merchant_id by request or hostname sub fetch_merchant { my $self = shift; my $q = shift; my $varenv = shift; my $req_coo = shift || ""; my $req_merchant_id = shift || ""; my $return = { aowner => "", merchant_id => "", project_id => "" }; my $merchanized = 0; my $aowner = 0; while ((my $merchant_conf, my $value) = each %{ $dbt->{merchant_ids}}) { #$bw->log("---> trying merchant select by session-cookie OR authcookie OR merchant_id: if($merchant_conf && (($req_coo && $req_coo =~ /$merchant_conf/) || ($req_merchant_id && $req_merchant_id eq $merchant_conf))){",$merchant_conf,""); if($merchant_conf && (($req_coo && $req_coo =~ /$merchant_conf$/) || ($req_merchant_id && $req_merchant_id eq $merchant_conf))){ $merchanized = 1; $aowner = $value->{id}; $return->{aowner} = $value->{id}; $return->{merchant_id} = $merchant_conf; $return->{project_id} = $value->{project}; my $lat = ""; my $lng = ""; if($value->{initMap}){ $value->{initMap} =~ s/\s//g; ($lat,$lng) = split(/,/,$value->{initMap}) if($value->{initMap} && $value->{initMap} =~ /\d+,\d+/); } if($lat && $lng){ $return->{init_map}->{center}->{latitude} = $lat; $return->{init_map}->{center}->{longitude} = $lng; $return->{init_map}->{radius} = "2.9"; } $bw->log("===> merchant select by $return->{project_id} session-cookie OR authcookie OR merchant_id: if($merchant_conf && (($req_coo && $req_coo =~ /$merchant_conf/) || ($req_merchant_id && $req_merchant_id eq $merchant_conf))){",$return->{merchant_id},""); #last; } } if(!$merchanized){ if($varenv->{syshost} eq "shareeapp-primary" || $varenv->{syshost} eq "shareedms-primary"){ $aowner = $dbt->{primary}->{sharee_primary}->{owner}; $return->{aowner} = $dbt->{primary}->{sharee_primary}->{owner}; $return->{merchant_id} = $dbt->{primary}->{sharee_primary}->{merchant_id}; $return->{project_id} = $dbt->{primary}->{sharee_primary}->{project}; $merchanized = 1; $bw->log("===> merchant select by $return->{project_id} primary dbname: sharee_primary:",$return->{merchant_id},""); } elsif($varenv->{syshost} =~ /shareeapp-(\w+)/ || $varenv->{syshost} =~ /shareedms-(\w+)/){ $aowner = $dbt->{operator}->{$varenv->{dbname}}->{owner}; $return->{aowner} = $dbt->{operator}->{$varenv->{dbname}}->{owner}; $return->{merchant_id} = $dbt->{operator}->{$varenv->{dbname}}->{merchant_id}; $return->{project_id} = $dbt->{operator}->{$varenv->{dbname}}->{project}; $merchanized = 1; $bw->log("===> merchant select by $return->{project_id} operator dbname=$varenv->{dbname}:",$return->{merchant_id},""); } elsif($varenv->{syshost} =~ /shareeweb-/){ $aowner = $dbt->{website}->{$varenv->{syshost}}->{owner}; $return->{aowner} = $dbt->{website}->{$varenv->{syshost}}->{owner}; $return->{merchant_id} = $dbt->{website}->{$varenv->{syshost}}->{merchant_id}; $return->{project_id} = $dbt->{website}->{$varenv->{syshost}}->{project}; $merchanized = 1; $bw->log("===> merchant select by $return->{project_id} website syshost=$varenv->{syshost}:",$return->{merchant_id},""); } } return ($aowner,$return); } #helper to get template sub get_node_meta { my $self = shift; my $viewsel = shift; my $ndesc = $dbt->get_node_meta($dbh,$viewsel); return $ndesc; } #helper to get node sub get_node { my $self = shift; my $main_id = shift; my $ndesc = $dbt->get_node($dbh,$main_id); return $ndesc; } #helper to get DMS users (used by servicetool) sub select_dmsusers { my $self = shift; my $u_id = shift || 0; my $sqlcon = shift || ""; my $users = $dbt->select_users($dbh,$u_id,$sqlcon); return $users; } #node_select sub template_select(){ my $self = shift; my $node = shift; my $return={}; #category means node.main_id. #template_id from contentpos.template_id #finally get tpl_order of contentpos if(ref($node) eq "HASH"){ my $node_record = $dbt->fetch_rel4tpl4nd($dbh,$node); my @tpl_order = split /,/,$node_record->{tpl_order}; foreach (@tpl_order){ my ($key,$val,$size,$interval) = split /=/,$_; $return->{$key} = ["$val","$size","$interval"]; } return ($return,$node_record); }else{ return "Failure 4003: category OR template must be defined as integer"; } }#end node_select #Search one by key sub service_work_search(){ my $self = shift; my $bike = shift || ""; my $station = shift || ""; my $history = shift || 0; my $search = shift || ""; my $bike_id = $1 if($bike =~ /(\d+)/); my $station_id = $1 if($station =~ /(\d+)/); my $dt1 = DateTime->now; my $return={}; my $pref = { table => "content", table_pos => "contentpos", fetch => "one", catch => "content_contentpos", keyfield => "c_id", }; if(looks_like_number($bike_id)){ $pref->{barcode} = "=::" . $bike_id; } if(looks_like_number($station_id)){ $pref->{int04} = "=::" . $station_id; } $pref = { %$pref, mtime => ">=::(now() - interval '$history day')" } if($history > 0); $pref = { %$pref, $search->{key} => "ilike::$search->{val}" } if(ref($search) eq "HASH" && $search->{key}); my $pos_record = $dbt->collect_post($dbh,$pref); return $pos_record; } #service_select by service_id=service-c_id sub service_select { my $self = shift; my $q = shift; my $auth = shift; my $service_id = shift || ""; my $interval = shift || ""; my $pos_record = {}; my $return = {}; my $bike = ""; my $station = ""; $bike = $1 if($q->param('bike') =~ /(\d+)/); $station = $1 if($q->param('station') =~ /(\d+)/); my $cpref = {}; my $c_table = "content"; my $pos_table = "contentpos"; my $template_id_pos = ""; #all this just get the right pos template_id if($q->param('request') eq "service_done" || $q->param('request') eq "service_work" || $q->param('request') eq "bikes_all"){ if(looks_like_number($bike)){ $cpref = { table => "$c_table", fetch => "one", template_id => "205", barcode => "=::" . $q->escapeHTML($bike), }; } if(looks_like_number($station)){ $cpref = { table => "$c_table", fetch => "one", template_id => "225", int04 => "=::" . $q->escapeHTML($station), }; } if($q->param('request') eq "bikes_all"){ $cpref = { table => "$c_table", fetch => "one", template_id => "205", }; } if($q->param('request') eq "bikes_all" && looks_like_number($station)){ $cpref = { table => "$c_table", fetch => "one", template_id => "205", }; } } elsif($q->param('request') eq "user_feedback"){ $c_table = "contentadr"; $pos_table = "contentadrpos"; $template_id_pos = 601;#feedback template_id $cpref = { table => "$c_table", fetch => "one", template_id => "202", c_id => "$auth->{c_id}", }; } elsif($q->param('request') eq "user_minianswer"){ $c_table = "contentadr"; $pos_table = "contentadrpos"; $template_id_pos = 602;#miniquery answer template_id $cpref = { table => "$c_table", fetch => "one", template_id => "202", c_id => "$auth->{c_id}", }; } #get real pos.template_id by parent_id=$crecord->{main_id} my $crecord = $dbt->fetch_record($dbh,$cpref); #will be only done if article (bike or station) exists in DB if(ref($crecord) eq "HASH" && $crecord->{c_id} && $crecord->{main_id}){ my $subrelnode = $dbt->get_subrelnode($dbh,$crecord->{main_id},$template_id_pos); #get service template to return template formated contentpos my ($tpl_order,$node_template) = $self->template_select($subrelnode); my @tpl_order = split /,/,$node_template->{tpl_order}; #only used by serviceapp if($q->param('request') ne "user_feedback" && $q->param('request') ne "user_minianswer"){ my $pref = { table => "$c_table", table_pos => "$pos_table", fetch => "all", catch => "content_contentpos", keyfield => "c_id", }; #Because of different contentpos.template_id in Flot Service we use it only on all others else bikes_all requests if($q->param('request') ne "bikes_all"){ $pref->{template_id} = "$node_template->{template_id}"; } if(looks_like_number($q->param('service_id'))){ $pref->{c_id} = "=::" . $q->escapeHTML($q->param('service_id')); }elsif(looks_like_number($service_id)){ $pref->{c_id} = "=::" . $service_id; }elsif(looks_like_number($bike)){ $pref->{barcode} = "=::" . $q->escapeHTML($bike); }elsif(looks_like_number($station)){ $pref->{int04} = "=::" . $q->escapeHTML($station); } if($cal->checkdate_time($q->param('timestamp'))){ $pref->{mtime} = "<=::" . $q->escapeHTML($q->param('timestamp')); } if(looks_like_number($interval) && $interval > 0){ if($interval == 30){ #get timestamp from 10. Aufgaben $pref->{txt01} = "cp.txt01 like '%' and cp.txt01 != 'NaN'"; $bw->log("service_select collect_post to get timestamp of tenth Aufgabe",$pref,""); my $pos_record10 = $dbt->collect_post($dbh,$pref,"10"); foreach my $id (sort { $pos_record10->{$b}->{c_id} <=> $pos_record10->{$a}->{c_id} } keys (%$pos_record10)){ $pref->{mtime} = ">=::$pos_record10->{$id}->{mtime}"; } delete $pref->{txt01}; }else{ $pref->{mtime} = ">=::(now() - interval '$interval day')"; } #if service saved by servicetool fetch user saved services <= 1day if($q->param('request') eq "service_done"){ $pref->{owner} = $auth->{c_id}; } } $bw->log("service_select collect_post with interval $interval",$pref,""); $pos_record = $dbt->collect_post($dbh,$pref); my $pos_count = 0; foreach my $id (sort { $pos_record->{$a}->{barcode} <=> $pos_record->{$b}->{barcode} } keys (%$pos_record)){ foreach (@tpl_order){ my ($key,$val,$size,$interval) = split /=/,$_; $pos_count++ if($key =~ /mtime/ && $pos_record->{$id}->{$key}); $return->{$id}->{$key} = $pos_record->{$id}->{$key} || ""; } } #only used on service init if($pos_table eq "contentpos" && !$pos_count){ foreach (@tpl_order){ my ($key,$val,$size,$interval) = split /=/,$_; if($key eq "txt01"){ $return->{1}->{$key} = "::erledigt::"; $pos_record->{1}->{$key} = "::erledigt::"; }else{ $return->{1}->{$key} = "1"; $pos_record->{1}->{$key} = "1"; } } $return->{1}->{barcode} = "$bike"; $return->{1}->{cc_id} = "$crecord->{c_id}"; $return->{1}->{mtime} = "$crecord->{mtime}"; $return->{1}->{owner} = "$crecord->{owner}"; $return->{1}->{template_id} = "$node_template->{template_id}"; $pos_record->{1}->{barcode} = $bike; $pos_record->{1}->{cc_id} = $crecord->{c_id}; $pos_record->{1}->{mtime} = $crecord->{mtime}; $pos_record->{1}->{owner} = $crecord->{owner}; $pos_record->{1}->{template_id} = $node_template->{template_id}; } $bw->log("service_select with node_template: $node_template->{template_id} and pos_record:",$pos_record,""); } return ($return,$pos_record,$node_template,$crecord); }#end if($crecord) else{ return ("","","",""); } }#end service_select #service_insert sub service_insert(){ my $self = shift; my $q = shift; my $auth = shift; my $node_template = shift || ""; my $crecord = shift || {}; my $owner = shift || 0; my $return={}; #insert pos with cc_id my $c_id = 0; if($q->param('request') eq "service_done" && ref($crecord) eq "HASH" && $crecord->{c_id} > 0){ my $insert = { table => "contentpos", cc_id => $crecord->{c_id}, barcode => $crecord->{barcode}, int04 => $crecord->{int04}, owner => $auth->{c_id}, template_id => $node_template->{template_id}, mtime => "now()", }; $c_id = $dbt->insert_contentoid($dbh,$insert,""); } if($q->param('request') eq "user_feedback" && ref($crecord) eq "HASH" && $crecord->{c_id} > 0){ my $bike_id = ""; my $insert = { table => "contentadrpos", ca_id => $crecord->{c_id}, txt01 => $auth->{txt01}, txt08 => $auth->{txt08}, owner => $owner, template_id => $node_template->{template_id}, mtime => "now()", }; if($q->param('bike') =~ /(\d+)/){ my $bike = $1; $insert->{barcode} = $bike; $c_id = $dbt->insert_contentoid($dbh,$insert,""); #if bike_broken then also to contentpos if(!$q->param('bike_broken')){ my $cpref = { table => "content", fetch => "one", template_id => "205", barcode => "$bike", }; my $crecord_content = $dbt->fetch_record($dbh,$cpref); if(ref($crecord_content) eq "HASH" && $crecord_content->{c_id} && $crecord_content->{main_id}){ my $subrelnode = $dbt->get_subrelnode($dbh,$crecord_content->{main_id},""); my ($tpl_order,$node_template_contentpos) = $self->template_select($subrelnode); my $insert_contentpos = { table => "contentpos", cc_id => $crecord_content->{c_id}, #int03 => $c_id, #yes, c_id from contentadrpos to make backlink barcode => $crecord_content->{barcode}, int04 => $crecord_content->{int04}, owner => $owner, template_id => $node_template_contentpos->{template_id}, mtime => "now()", }; #$update->{int01} = 1 if($q->param('bike_broken'));#TODO. what should else be done if bike_broken $insert_contentpos->{txt01} = $q->escapeHTML($q->param('message')) if($q->param('message')); my $c_id_contentpos = $dbt->insert_contentoid($dbh,$insert_contentpos,""); } } } } if($q->param('request') eq "user_minianswer" && ref($crecord) eq "HASH" && $crecord->{c_id} > 0){ my $insert = { table => "contentadrpos", #ca_id => $crecord->{c_id},#have to be anonym owner => $owner, template_id => $node_template->{template_id}, mtime => "now()", }; $c_id = $dbt->insert_contentoid($dbh,$insert,""); } return $c_id; }#end service_insert #service_update sub service_update(){ my $self = shift; my $q = shift; my $auth = shift; my $node_template = shift; my $c_id = shift || ""; my $action = shift || ""; my $return={}; my $update = {}; if($q->param('request') eq "service_done"){ $c_id = $q->param('service_id') if($q->param('service_id')); $update = { table => "contentpos", owner => $auth->{c_id}, mtime => "now()", }; }elsif($q->param('request') eq "user_feedback"){ $update = { table => "contentadrpos", mtime => "now()", int01 => 0, }; $update->{int01} = 1 if($q->param('bike_broken')); $update->{txt02} = $q->escapeHTML($q->param('message')) if($q->param('message')); }elsif($q->param('request') eq "user_minianswer"){ $update = { table => "contentadrpos", mtime => "now()", }; $update->{txt01} = $q->escapeHTML($q->param('q1')) if($q->param('q1')); $update->{txt02} = $q->escapeHTML($q->param('q2')) if($q->param('q2')); $update->{txt03} = $q->escapeHTML($q->param('q3')) if($q->param('q3')); my $last_used_operator = $auth->{txt19}; if($last_used_operator){ my $dbh_operator = $dbt->dbconnect_extern("$last_used_operator"); my $postref = { table => "contenttrans", table_pos => "contenttranspos", fetch => "one", ca_id => "$auth->{c_id}", int26 => ">::0.1",#if cloud distance km > 0,1 end_time => ">=::(now() - interval '10 minutes')", }; my $post_record = $dbt->collect_post($dbh_operator,$postref); $update->{int02} = $post_record->{int26} if($post_record->{int26}); $update->{txt10} = $dbt->{operator}->{$last_used_operator}->{oprefix}; } } my $record = { c_id => $c_id }; $node_template->{tpl_order} .= ",txt09=Wartungsarbeiten"; my @tpl_order = split /,/,$node_template->{tpl_order}; if($action){ my ($key,$val) = split /=/,$action; $update->{$key} = $val if($key eq "txt10");#pos station log on redistribution }elsif($q->param('work_id')){ foreach (@tpl_order){ my ($key,$val,$size) = split /=/,$_; #key validation will be done by update_record if($key eq "txt01" && $q->param('work_id') eq "$key" && $q->param('work_val') =~ /::erledigt::/){ my $pref_pos = { table => "contentpos", fetch => "one", c_id => $c_id, }; my $record_pos = $dbt->fetch_tablerecord($dbh,$pref_pos) if($c_id); if($record_pos->{txt01} ne "NaN"){ $update->{$key} = $q->escapeHTML($q->param('work_val')) . " " . $record_pos->{txt01} if($record_pos->{txt01} !~ /::erledigt::/); }else{ $update->{$key} = $q->escapeHTML($q->param('work_val')); } } elsif($key eq "txt01" && $q->param('work_id') eq "$key" && $q->param('work_val') !~ /\w/){ $update->{$key} = "NaN"; } elsif($q->param('work_id') eq "$key"){ $update->{$key} = $q->escapeHTML($q->param('work_val')); } } }elsif(1==2){#TODO template key REST mapping my @keywords = $q->param; foreach (@tpl_order){ my ($key,$val,$size,$interval) = split /=/,$_; foreach(@keywords){ if($_ eq $key){ #key validation will be done by update_record $update->{$_} = $q->escapeHTML($q->param($key)); } } #unchecked checkbox doesn't deliver values. Thats the solution #disabled delete values at all. Test with json API conflicts because we disabled checkboxes #$update->{$key} = "null" if($key =~ /^int\d+$/ && $key !~ /^int04/ && !looks_like_number($update->{$key})); #$update->{$key} = "NaN" if($key =~ /^txt01$/ && !$update->{$key});#sepcial on TINK Service } } my $rows = $dbt->update_record($dbh,$update,$record) if($record->{c_id} > 0); return $rows; }#end service_update #bike_update for state update after servíce_work (cronjob) OR service_done sub bikestate_update(){ my $self = shift; my $auth = shift; my $c_id = shift || ""; my $state = shift || ""; my $update_hash = shift || ""; my %varenv = $cf->envonline(); my $return={}; my $update = { table => "content", owner => $auth->{c_id}, mtime => "now()", }; #set state only if defined $update->{int10} = $state if($state); #moving bike to station if(ref($update_hash) eq "HASH" && looks_like_number($update_hash->{int04})){ $update->{int04} = "$update_hash->{int04}"; } $bw->log("check state on bikestate_update 1.",$update,""); my $record = { c_id => $c_id }; my $rows = $dbt->update_record($dbh,$update,$record) if($record->{c_id} > 0); #require "Mod/KMLout.pm"; #my $kmlfile = KMLout::kmlGenerator($auth,""); return $rows; }#bikestate_update #feedback response --> obsolet sub feedback_response { my $self = shift; my $pos_record = shift; my $node_template = shift; my %varenv = $cf->envonline(); my @tpl_order = split /,/,$node_template->{tpl_order}; my $return = {}; foreach my $id (sort { $pos_record->{$a}->{mtime} cmp $pos_record->{$b}->{mtime} } keys (%$pos_record)){ foreach (@tpl_order){ my ($key,$val,$size) = split /=/,$_; $return->{feedback_id} = "$pos_record->{$id}->{c_id}" if($key eq "c_id"); $return->{bike} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}$pos_record->{$id}->{barcode}" if($key eq "barcode"); $return->{bike_broken} = "$pos_record->{$id}->{int01}" || "" if($key eq "int01"); $return->{message} = "$pos_record->{$id}->{txt02}" || "" if($key eq "txt02"); } } return $return; } #service_work copy from service_select sub service_work { my $self = shift; my $pos_record = shift; my $article_all = shift || ""; my $history = shift || 0; my $node_template = shift || {}; my %varenv = $cf->envonline(); my $dt1 = DateTime->now; my $return={}; my $mapref = { int09 => 1, }; #my $users_map = $dbt->users_map($dbh,$mapref);#get serviceAPP users my $users_map = $dbt->users_map($dbh,"");#get all serviceAPP users (also without service key) my $channel_map = $dbt->channel_map(); my @tpl_order = (); @tpl_order = split /,/,$node_template->{tpl_order} if(ref($node_template) eq "HASH" && $node_template->{tpl_order}); #because of different templates we need template grouping #not safe, pos template_id have to be defined before any service has done! #keep in mind, on pos tables there isn't any relation. That's because history pos.template_id will be selected my $pref = { table => "content", table_pos => "contentpos", }; my $template_group = $dbt->pos_template_group($dbh,$pref); #$bw->log(" template_group",$template_group,""); my $node = {}; my $op_return = {}; foreach my $cid (sort { $article_all->{$a}->{barcode} <=> $article_all->{$b}->{barcode} } keys(%$article_all)){ my $i=0; my $article = $article_all->{$cid}->{barcode}; my $tpl_keyseen = ""; #breaks JSON hash. don't do it #$return->{$bike}->{uri_operator} = "$varenv{wwwhost}"; foreach my $id (sort { $pos_record->{$a}->{mtime} cmp $pos_record->{$b}->{mtime} } keys (%$pos_record)){ $i++; if($article_all->{$cid}->{c_id} == $pos_record->{$id}->{cc_id}){ $article = $article_all->{$cid}->{barcode} if($article_all->{$cid}->{template_id} && $article_all->{$cid}->{template_id} == 205);# bike template_id $article = $article_all->{$cid}->{int04} if($article_all->{$cid}->{template_id} && $article_all->{$cid}->{template_id} == 225);# station template_id #breaks JSON hash. don't do it #$return->{$article}->{template_id} = "$pos_record->{$id}->{template_id}"; if(1==1){ if($pos_record->{$id}->{template_id} && $template_group->{$pos_record->{$id}->{template_id}}){ $bw->log("$article --> service_work template on id: $id used:",$template_group->{$pos_record->{$id}->{template_id}}->{tpl_id},""); @tpl_order = split /,/,$template_group->{$pos_record->{$id}->{template_id}}->{tpl_order}; $node->{template_id} = "$pos_record->{$id}->{template_id}"; }elsif(1==1){#on init use node tpl $bw->log("$article --> service_work template on id: $id used node_template:",$node->{template_id},""); my $tpl = $dbt->get_tpl($dbh,$node_template->{template_id}); @tpl_order = split /,/,$tpl->{tpl_order}; $node->{template_id} = "$tpl->{tpl_id}"; } foreach (@tpl_order){ my ($key,$val,$size,$interval,$service_type) = split /=/,$_; $service_type = 0 if(!looks_like_number($service_type)); my $erledigt = 0; $erledigt = 1 if(!$history && $pos_record->{$id}->{txt01} && $pos_record->{$id}->{txt01} !~ /::erledigt::/); $erledigt = 1 if($history && $pos_record->{$id}->{txt01} && $pos_record->{$id}->{txt01} =~ /::erledigt::/); if((($key =~ /int/ && looks_like_number($pos_record->{$id}->{$key})) || ($key eq "txt01" && $pos_record->{$id}->{$key} && $pos_record->{$id}->{$key} ne "NaN" && $erledigt))){ $tpl_keyseen .= "$key|"; $bw->log("$pos_record->{$id}->{barcode} --> if((($key =~ /int/ && looks_like_number($pos_record->{$id}->{$key})) || ($key eq \"txt01\" && $pos_record->{$id}->{$key} && $pos_record->{$id}->{$key} ne \"NaN\"))){",$tpl_keyseen,""); my $u_name = $users_map->{$pos_record->{$id}->{owner}}->{txt01} || $channel_map->{$pos_record->{$id}->{owner}} || $pos_record->{$id}->{owner}; my $dt2 = DateTime::Format::Pg->parse_datetime($pos_record->{$id}->{mtime}); my $time_over = "0"; if(looks_like_number($interval) && $interval > 0){ my $dt2_over = $dt2->add( days => $interval ); $bw->log("service-interval: $interval | $dt1 > $dt2_over (mtime: $pos_record->{$id}->{mtime})",$key,""); $time_over = "1" if($dt1 > $dt2_over); } my $key_change = $key; if($history && $history > 0){ my $dtstamp = $pos_record->{$id}->{mtime}; $dtstamp = $dt2->epoch(); $key_change .= "_" . $dtstamp; } $return->{$article}->{$key_change}->{service_id} = "$pos_record->{$id}->{c_id}"; $return->{$article}->{$key_change}->{work_id} = "$key"; $return->{$article}->{$key_change}->{work_name} = "$val"; $return->{$article}->{$key_change}->{interval} = "$interval"; $return->{$article}->{$key_change}->{time_over} = "$time_over"; $return->{$article}->{$key_change}->{service_type} = "$service_type"; $return->{$article}->{$key_change}->{work_val} = "$pos_record->{$id}->{$key}" if($key =~ /int/); $return->{$article}->{$key_change}->{work_val} .= "$pos_record->{$id}->{$key}" if($key =~ /txt/); $return->{$article}->{$key_change}->{mtime} = "$pos_record->{$id}->{mtime}"; $return->{$article}->{$key_change}->{user_name} = "$u_name"; $return->{$article}->{$key_change}->{owner} = "$pos_record->{$id}->{owner}"; } } } } } #set init values $bw->log("set service init values by @tpl_order","",""); if(!$history && scalar(@tpl_order) > 1){ $bw->log("tpl_keyseen",$tpl_keyseen,""); $tpl_keyseen =~ s/\|$//; foreach (@tpl_order){ my ($key,$val,$size,$interval,$service_type) = split /=/,$_; $service_type = 0 if(!looks_like_number($service_type)); if($key =~ /int|txt/ && (!$tpl_keyseen || $key !~ /$tpl_keyseen/)){ $return->{$article}->{$key}->{service_id} = "1"; $return->{$article}->{$key}->{work_id} = "$key"; $return->{$article}->{$key}->{work_name} = "$val"; $return->{$article}->{$key}->{interval} = "$interval"; $return->{$article}->{$key}->{time_over} = "1";#2021-06-23 if not seen then time_over $return->{$article}->{$key}->{service_type} = "$service_type"; $return->{$article}->{$key}->{work_val} = "1" if($key =~ /int/); $return->{$article}->{$key}->{work_val} = "::erledigt::" if($key =~ /txt/); $return->{$article}->{$key}->{mtime} = "2022-01-18 00:00"; $return->{$article}->{$key}->{user_name} = "init"; $return->{$article}->{$key}->{owner} = "188"; } } #}else{ #$return->{response_state} = "Failure 3099: history to short OR template fails"; } } return ($return,$node); }#end service_work #check and set user-bike rental tarif sub fetch_bike_tariff { my $self = shift; my $varenv = shift; my $auth = shift; my $bike = shift; my $owner = shift; my $bike_id = $bike || ""; $bike_id =~ s/S[1-9]X/SX/; $bike_id = $1 if($bike_id =~ /(\d+)/); my $main_ids = ""; my ($bike_group,$user_group,$tariff_content,$user_tour) = $self->fetch_tariff($varenv->{dbname},$auth,""); $main_ids = join(",",@{$bike_group}); $main_ids =~ s/[a-z_]+//ig; my $ct_bike = {}; my $pref_cc = { table => "content", fetch => "one", main_id => "IN::($main_ids)", barcode => $bike_id, #int10 => 1, }; $ct_bike = $dbt->fetch_record($dbh,$pref_cc) if($main_ids); #$tariff_nr in contentadr are saved by copri or user tarif-select!!! my $tariff_nr = ""; my @adr_tariff = (); if($auth->{txt30}){ @adr_tariff = ("$auth->{txt30}"); @adr_tariff = split(/\s+/,$auth->{txt30}) if($auth->{txt30} =~ /\w\s+\w/); } #This is the automatic user tariff setter if(ref($ct_bike) eq "HASH" && $ct_bike->{main_id}){ foreach my $id (keys (%$tariff_content)){ foreach(@adr_tariff){ $bw->log("booking_request adr_tariff array form $auth->{txt30}",$_,""); if($tariff_content->{$id}->{int12} && $tariff_content->{$id}->{int12} == $ct_bike->{main_id} && $tariff_content->{$id}->{barcode} && $_ == $tariff_content->{$id}->{barcode}){ $bw->log("booking_request tariff loop matches:",$tariff_content->{$id}->{barcode},""); $tariff_nr = $tariff_content->{$id}->{barcode}; } } } #if no tarif then update user account to fallback default public or private or hidden tarif if(!$tariff_nr){ my $update_adr = { table => "contentadr", mtime => "now()", owner => "$owner", c_id => "$auth->{c_id}", }; my @txt30 = (); foreach my $id (keys (%$tariff_content)){ # if($tariff_content->{$id}->{int18} && ($tariff_content->{$id}->{int18} == 2 || $tariff_content->{$id}->{int18} == 3 || $tariff_content->{$id}->{int18} == 4)){ #auto set tarif if requested bike matches flot if($tariff_content->{$id}->{int12} && $tariff_content->{$id}->{int12} == $ct_bike->{main_id} && $tariff_content->{$id}->{barcode}){ $bw->log("booking_request tariff loop matches:",$tariff_content->{$id}->{barcode},""); $tariff_nr = $tariff_content->{$id}->{barcode}; push(@txt30, "$tariff_content->{$id}->{barcode}"); } #add also other public tarif elsif($tariff_content->{$id}->{int18} && $tariff_content->{$id}->{int18} == 2 && $tariff_content->{$id}->{int12} && $tariff_content->{$id}->{barcode}){ push(@txt30, "$tariff_content->{$id}->{barcode}"); } } } $bw->log("booking_request NO user tariff defined, update user account to fallback default public or private or hidden",\@txt30,""); $dbt->update_one($dbh,$update_adr,"txt30='@txt30'"); }else{ $bw->log("booking_request user tariff selected",$tariff_nr,""); } } $bw->log("booking_request fetch_bike_tariff result ---> bike $ct_bike->{barcode} matching by bike_group: @{$bike_group} main_ids:$main_ids | user_group:@{$user_group} | Tarif selected: $tariff_nr",$tariff_content->{$tariff_nr},""); return ($ct_bike,$tariff_content->{$tariff_nr}); } #2022-04-05 refactored bike reservation sub booking_request(){ my $self = shift; my $varenv = shift; my $auth = shift;#app API auth my $bike = shift || "";#app API request my $ct_bike = shift || {}; my $ct_tariff = shift; my $owner = shift || ""; my $gps = shift || ""; my $sig_book = shift || {}; my $dbh = ""; my $pos_id=""; my $now_dt = strftime "%Y-%m-%d %H:%M", localtime; my $response_state = "OK"; my $response_text = ""; $bw->log("booking_request bike $bike, auth $auth->{c_id}, tarif $ct_tariff->{barcode}, requested bike:",$bike,""); my $update_adr = { table => "contentadr", mtime => "now()", owner => "$owner", c_id => "$auth->{c_id}", }; my $pref = { table => "contenttrans", fetch => "one", main_id => 300008, template_id => 218, #ca_id => "$auth->{c_id}",#future change int10 => "$auth->{c_id}", state => "null", close_time => "is::null", }; #if bike and tariff if($ct_bike->{barcode} && $ct_tariff->{barcode}){ my $ctt = {}; my $rentable_check=0; $rentable_check = $self->isuser_rentable($auth,$varenv); $bw->log("booking_request isuser_rentable:",$rentable_check,""); if($rentable_check == 2){ #get invoice $ctt = $dbt->fetch_record($dbh,$pref); if(!$ctt->{c_id}){ my $ct_id = $dbt->insert_contenttrans($dbh,$auth,"300008","218","----","$owner"); $pref->{c_id} = $ct_id; $ctt = $dbt->fetch_record($dbh,$pref) if($pref->{c_id}); } $bw->log("booking_request used invoice c_id:",$ctt->{c_id},""); #if invoice exist if($ctt->{c_id}){ #2 = "requested" $pos_id = $dbt->insert_pos($dbh,$ctt->{c_id},$ct_bike,$auth,$ct_tariff,$now_dt,$bike,"2",$owner,$sig_book); $bw->log("booking_request insert_pos:",$pos_id,""); if($pos_id){ $response_state = "OK, bike " . $bike . " succesfully requested"; $response_text = "Fahrrad Nr. $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}, }; $dbt->update_one($dbh,$update_ctt,"start_time='$now_dt'"); }else{ $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"; } } }elsif($rentable_check == 1){ $response_state="Failure 1006: There is no valid payment methode"; $response_text="Bitte überprüfen Sie Ihre Profildaten auf Vollständigkeit, nur dann können wir das Mietradsystem für Sie freischalten"; }else{ my $vde = $auth->{int12} || 1; $dbt->update_one($dbh,$update_adr,"int12=$vde"); $response_state="Failure 1005: user-account deactivated because of failing data"; $response_text="Bitte überprüfen Sie Ihre Profildaten auf Vollständigkeit, nur dann können wir das Mietradsystem für Sie freischalten"; } } my $return = { bike => "$bike", state => "requested", response_state => "$response_state", response_text => "$response_text" }; $bw->log("booking_request response_state:",$return,""); return $return; } #int03=1 if sepa, 2=CC #int04==1 if email Ack #int13==1 if sms Ack #int12!=1|2|3 if Vde #int14==1 if AGB sub isuser_rentable { my $self = shift; my $auth = shift; my $varenv = shift; my $rentable_check=0; if(($auth->{int03} == 1 && $auth->{ct_name} =~ /\w{2}-\d+/ && $auth->{ct_name} !~ /LV-\d+/) || ($auth->{int03} == 2 && length($auth->{ct_name}) >= 19) || ($auth->{int03} == 1 && $varenv->{dbname} eq "sharee_lv" && $auth->{ct_name} =~ /LV-\d+/)){ $rentable_check=1; if($auth->{txt08} && $auth->{int04} == 1 && $auth->{int13} == 1 && !$auth->{int12} && $auth->{int14}){ $rentable_check=2; } } return $rentable_check; } #booking_cancel changed to booking_update sub booking_update(){ my $self = shift; my $q = shift; my $varenv = shift; my $auth = shift; my $owner = shift || 0; my $sig_book = shift || {}; my $state = $q->escapeHTML($q->param('state')) || ""; my $lock_state = $q->escapeHTML($q->param('lock_state')) || ""; my $station_state = $q->escapeHTML($q->param('station_state')) || ""; my %varenv = $cf->envonline(); my $rows = 0; my $user_agent = $q->user_agent(); my $record_pos = { c_id => 0 };#if fails #my $bike = $q->param('bike'); #my $bike_id = $1 if($q->escapeHTML($q->param('bike')) =~ /(\d+)/); my $bike = $q->escapeHTML($q->param('bike')) || ""; my $bike_id = $bike; $bike_id =~ s/S[1-9]X/SX/; $bike_id = $1 if($bike_id =~ /(\d+)/); my $state_key = 0; my $state_text = ""; while (my ($key, $value) = each %{ $dbt->{copri_conf}->{bike_state} }) { if($state eq $value){ $state_key = $key; $state_text = "beendet" if($state eq "available"); $state_text = "gestartet" if($state eq "occupied"); } } my $booking_values = { bike => "$bike", state => "", lock_state => "", station_state => "", co2saving => "", response_state => "OK 1017: No update", response_text => "Der Mietstatus wurde nicht geändert.", }; my $pref = { table => "contenttrans", table_pos => "contenttranspos", fetch => "one", template_id => "218",#Mietjournal tpl_id barcode => $bike_id, ca_id => "$auth->{c_id}", "ct.close_time" => "is::null", #txt10 => "IN::('occupied','requested')", int10 => "IN::('3','2')", }; $record_pos = $dbt->collect_post($dbh,$pref) if($q->param('bike')); my $pref_cc = { table => "content", fetch => "one", template_id => "205", barcode => $bike_id, }; my $record_cc = $dbt->fetch_record($dbh,$pref_cc) if($q->param('bike')); $bw->log("booking_update bike to state $bike $state ($state_key) $lock_state, auth $auth->{c_id}, bike:",$bike,""); my $update_cc = { table => "content", mtime => "now()", owner => "$owner", }; my $gps = ""; my $latitude = ""; my $longitude = ""; #old if($q->param('gps')){ my $gps_input = $q->param('gps'); $gps_input =~ s/\s//g; $latitude = $q->escapeHTML($1) if($gps_input =~ /^(\d+\.\d+),\d+/); $longitude = $q->escapeHTML($1) if($gps_input =~ /\d+,(\d+\.\d+)$/); $gps = "$latitude,$longitude" if($latitude && $longitude); } #new if($q->param('latitude') && $q->param('longitude')){ my $latitude_in = $q->param('latitude'); my $longitude_in = $q->param('longitude'); $latitude = $1 if($latitude_in =~ /(\d+\.\d+)/); $longitude = $1 if($longitude_in =~ /(\d+\.\d+)/); $gps = "$latitude,$longitude" if($latitude && $longitude); } my $Ilockit_GUID = ""; $Ilockit_GUID = $q->escapeHTML($q->param('Ilockit_GUID')) if($q->param('Ilockit_GUID') && $q->param('Ilockit_GUID') =~ /\w+-\w+-\w+-\w+$/); my $gps_age = 0; my $gps_age_minutes = 60; $gps_age = $q->escapeHTML($1) if($q->param('gps_age') =~ /^(\d+)/);#in milli-sec $gps_age_minutes = $gps_age / 1000 / 60 if($gps_age); my $gps_accuracy = 0; $gps_accuracy = $q->escapeHTML($1) if($q->param('gps_accuracy') =~ /^(\d+)/);#in meters my $geo_distance = 1000000;#defaults to 1000000 Meter #my $ct_state = $state; my $ct_state = $record_pos->{int10};#2020-07-25 changed because ct_state cannot be canceled #2020-09-24 requested will be all done by net_booking #6 = "canceled"|3 = "occupied"|1 = "available" #if($state && $state =~ /$dbt->{copri_conf}->{bike_state}->{6}|$dbt->{copri_conf}->{bike_state}->{3}|$dbt->{copri_conf}->{bike_state}->{1}/ && $record_pos->{cc_id} && $record_pos->{cc_id} > 0){ if($state_key && ($state_key == 6 || $state_key == 3 || $state_key == 1) && $record_pos->{cc_id} && $record_pos->{cc_id} > 0){ #set rent state if lock_system 2=Ilockit || 3=sigo if($record_pos->{int11} && ($record_pos->{int11} == 2 || $record_pos->{int11} == 3)){ my $update_pos = { table => "contenttranspos", #int10 => "$state_key", mtime => "now()", }; $update_pos->{txt21} = $q->escapeHTML($q->param('user_device')) if($q->param('user_device')); $update_pos->{txt26} = $q->escapeHTML($user_agent) if($user_agent); #if($state =~ /canceled/ && $record_pos->{txt10} =~ /requested/) if($state_key == 6 && $record_pos->{int10} == 2){ $rows = $dbt->delete_content($dbh,"contenttranspos",$record_pos->{c_id}); if($rows > 0){ $ct_state = "1";#1 = "available" $booking_values->{response_state} = "OK: canceled bike " . $q->param('bike'); $booking_values->{response_text} = "Fahrrad Nr. " . $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 Fahrrad Nr. " . $q->param('bike') . " gefunden."; } }else{ $update_pos->{txt17} = $Ilockit_GUID if($Ilockit_GUID); #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")){ $update_pos->{start_time} = "now()"; $update_pos->{end_time} = "now()"; #$update_pos->{txt05} = "$gps";#start GPS, not exist on request $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 $update_pos->{int21} = "$gps_age_minutes"; $update_pos->{int22} = "$gps_accuracy"; $update_pos->{owner} = "$owner"; $update_pos->{int10} = "$state_key"; $update_pos->{txt11} = "$sig_book->{rentalId}" if($sig_book->{rentalId}); $rows = $dbt->update_record($dbh,$update_pos,$record_pos); if($rows > 0){ $booking_values->{response_state} = "OK: occupied bike " . $q->param('bike'); $booking_values->{response_text} = "Fahrrad Nr. " . $q->param('bike') . " Miete gestartet. "; $ct_state = $state_key; } #Mietende request state=available and pos-state 2=requested or 3=occupied }elsif($state_key == 1 && ($record_pos->{int10} == 2 || $record_pos->{int10} == 3)){ #int24 == 1 if if locked && end gps && end station && gps_age <= 3 min && in geo_fence if($record_pos->{int24}){ $update_pos->{owner_end} = "$owner"; $update_pos->{end_time} = "now()"; #return after booking_update #my $pricing = $pri->sharee_pricing($record_pos,"calc_price"); #new sharee_pricing my ($pricing,$counting) = $pri->counting_rental(\%varenv,$record_pos,"calc_price"); #int03 only used for tarif counting backwards compatibility $update_pos->{int03} = "$pricing->{computed_hours}" if(looks_like_number($pricing->{computed_hours})); $update_pos->{int38} = "$counting->{int38}" if(looks_like_number($counting->{int38})); $update_pos->{int39} = "$counting->{int39}" if(looks_like_number($counting->{int39})); $update_pos->{int40} = "$counting->{int40}" if(looks_like_number($counting->{int40})); $update_pos->{int41} = "$counting->{int41}" if(looks_like_number($counting->{int41})); $update_pos->{int10} = "$state_key"; $update_pos->{txt11} = "$sig_book->{rentalId}" if($sig_book->{rentalId}); $rows = $dbt->update_record($dbh,$update_pos,$record_pos); $booking_values->{response_state} = "OK: available bike " . $q->param('bike') . ", still locked"; $booking_values->{response_text} = "Danke! Die Miete Fahrrad Nr. " . $q->param('bike') . " wurde beendet. Schloß wurde bereits abgeschlossen."; $ct_state = $state_key; } #client GPS must have. sigo ist done without client gps elsif(($gps && $gps_age_minutes <= 3) || ($record_pos->{int11} == 3)){ #geofencing for Ilockit my $geo_distance_next = 100000; my $station_next = 0; my $geo_debug=""; my ($stations,$stations_raw) = $self->stations_available($q,$varenv,$auth); foreach my $id (sort { $stations_raw->{$a}->{barcode} <=> $stations_raw->{$b}->{barcode} } keys (%$stations_raw)){ my $latitude_station = $1 if($stations_raw->{$id}->{txt06} =~ /^(\d+\.\d+)/); my $longitude_station = $1 if($stations_raw->{$id}->{txt06} =~ /(\d+\.\d+)$/); if((!looks_like_number($latitude) || !looks_like_number($longitude)) && ($record_pos->{int11} != 3)){ $geo_debug .= "ERROR no user GPS: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; }elsif((looks_like_number($latitude) && looks_like_number($longitude) && looks_like_number($latitude_station) && looks_like_number($longitude_station)) || ($record_pos->{int11} == 3)){ $update_pos->{owner_end} = "$owner"; $update_pos->{end_time} = "now()"; $geo_distance = $lb->geo_fencing($latitude,$longitude,$latitude_station,$longitude_station); #$station_next = $stations_raw->{$id}->{int04}; #if($geo_distance <= $stations_raw->{$id}->{int06}){ #sigo development workaround without geofence if(($geo_distance <= $stations_raw->{$id}->{int06}) || ($record_pos->{int11} == 3)){ $geo_distance_next = $geo_distance; #end-Station $update_pos->{int04} = "$stations_raw->{$id}->{int04}"; $update_cc->{int04} = "$stations_raw->{$id}->{int04}"; $update_pos->{int24} = "1"; $update_pos->{int10} = "$state_key"; $update_pos->{txt11} = "$sig_book->{rentalId}" if($sig_book->{rentalId}); $update_cc->{txt06} = "$gps";#end content coordinates $update_pos->{txt06} = "$gps";#end pos coordinates $update_pos->{int21} = "$gps_age_minutes"; $update_pos->{int22} = "$gps_accuracy"; $update_pos->{int23} = "$geo_distance"; #end-Station prefix $update_pos->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}"; #end-Station prefix $update_cc->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}"; #return after booking_update #my $pricing = $pri->sharee_pricing($record_pos,"calc_price"); #new sharee_pricing my ($pricing,$counting) = $pri->counting_rental(\%varenv,$record_pos,"calc_price"); #int03 only used for tarif counting backwards compatibility $update_pos->{int03} = "$pricing->{computed_hours}" if(looks_like_number($pricing->{computed_hours})); $update_pos->{int38} = "$counting->{int38}" if(looks_like_number($counting->{int38})); $update_pos->{int39} = "$counting->{int39}" if(looks_like_number($counting->{int39})); $update_pos->{int40} = "$counting->{int40}" if(looks_like_number($counting->{int40})); $update_pos->{int41} = "$counting->{int41}" if(looks_like_number($counting->{int41})); $rows = $dbt->update_record($dbh,$update_pos,$record_pos); if($rows > 0){ $booking_values->{response_state} = "OK: available bike " . $q->param('bike'); $booking_values->{response_text} = "Danke! Die Miete Fahrrad Nr. " . $q->param('bike') . " wurde beendet."; $ct_state = $state_key; } $geo_debug .= "Matching station: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; last; }else{ if($geo_distance <= $geo_distance_next){ $geo_distance_next = $geo_distance; $station_next = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}$stations_raw->{$id}->{int04}"; } #2021-10-13 changed to save last gps @all $update_cc->{txt06} = "$gps";#end content coordinates $update_pos->{txt06} = "$gps";#end pos coordinates $update_pos->{int21} = "$gps_age_minutes"; $update_pos->{int22} = "$gps_accuracy"; $update_pos->{int23} = "$geo_distance"; #end-Station prefix $update_pos->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}"; #end-Station prefix $update_cc->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}"; #return after booking_update #my $pricing = $pri->sharee_pricing($record_pos,"calc_price"); #new sharee_pricing my ($pricing,$counting) = $pri->counting_rental(\%varenv,$record_pos,"calc_price"); #int03 only used for tarif counting backwards compatibility $update_pos->{int03} = "$pricing->{computed_hours}" if(looks_like_number($pricing->{computed_hours})); $update_pos->{int38} = "$counting->{int38}" if(looks_like_number($counting->{int38})); $update_pos->{int39} = "$counting->{int39}" if(looks_like_number($counting->{int39})); $update_pos->{int40} = "$counting->{int40}" if(looks_like_number($counting->{int40})); $update_pos->{int41} = "$counting->{int41}" if(looks_like_number($counting->{int41})); $rows = $dbt->update_record($dbh,$update_pos,$record_pos); $geo_debug .= "Out of station distance: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance_next Meter ($geo_distance_next <= $geo_distance) station_next: $station_next\n"; $booking_values->{response_state} = "Failure 2178: bike " . $q->param('bike') . " out of GEO fencing. $geo_distance_next meter distance to next station $station_next ."; $booking_values->{response_text} = "Achtung! Ihr aktueller Standort liegt außerhalb einer Fahrradstation. Die Miete Fahrrad Nr. " . $q->param('bike') . " kann nicht $state_text werden. $geo_distance_next Meter Entfernung zur nächsten Station $station_next . Falls Sie sich doch an einer Station befinden, dann wiederholen Sie \"Miete beenden\"."; } }else{ $geo_debug .= "ERROR no station GPS: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; } } $booking_values->{geo_distance} = "$geo_distance_next"; #print "$geo_debug\n"; $bw->log("GEOfencing geo_debug:$geo_debug",$q,""); #end if gps && gps_age <= 3 and not sigo }elsif($record_pos->{int11} != 3){ if(!$gps){ $booking_values->{response_state} = "Failure 2245: No GPS data, state change forbidden."; $booking_values->{response_text} = "Fehler! Keine GPS Standortdaten, Die Miete Fahrrad Nr. " . $q->param('bike') . " kann wegen fehlendem GPS nicht $state_text werden. Bitte aktivieren Sie das GPS."; }else{ $booking_values->{response_state} = "Failure 2246: GPS age with $gps_age_minutes minutes too old, state change forbidden."; $booking_values->{response_text} = "Fehler! GPS Daten sind mit $gps_age_minutes Minuten zu alt. Die Miete Fahrrad Nr. " . $q->param('bike') . " kann aufgrund nicht aktueller GPS nicht $state_text werden. Bitte aktivieren Sie das GPS."; } } #end if($state eq "available" && }elsif($state_key == 6 && $record_pos->{int10} == 3){ $booking_values->{response_state} = "Failure 2012: occupied bike " . $q->param('bike') . " cannot be $state"; $booking_values->{response_text} = "Fahrrad Nr. " . $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} = "Fahrrad Nr. " . $q->param('bike') . " wurde nicht reserviert und kann somit nicht gemietet werden."; }else{ $booking_values->{response_state} = "Failure 2035: bike " . $q->param('bike') . " state change to $state not possible."; $booking_values->{response_text} = "Fehler! Die Miete Fahrrad Nr. " . $q->param('bike') . " kann nicht mit dem vorhandenen Status $state_text werden."; } #contenttrans my $update_ct = { table => "contenttrans", mtime => "now()", owner => "$owner", }; my $record_ct->{c_id} = $record_pos->{ct_id}; $dbt->update_record($dbh,$update_ct,$record_ct); if($q->param('voltage') && $q->param('voltage') =~ /(\d+)/){ $update_cc->{int14} = $1; #$self->service_automatic($q) if($1 <= 40); } $update_cc->{txt15} = $q->escapeHTML($q->param('firmware')) if($q->param('firmware')); $update_cc->{txt17} = $Ilockit_GUID if($Ilockit_GUID); } #end Ilockit || sigo }else{ $bw->log("smartlock type not defined, int11:",$record_pos->{int11},""); } #update bike content $update_cc->{int10} = "$ct_state";#yes we believe it unsafe to get failure #if(looks_like_number($ct_state)); $bw->log("check ct_state on update_cc 2.",$update_cc,""); #my $record_cc = { c_id => $record_pos->{cc_id} }; $dbt->update_record($dbh,$update_cc,$record_cc); #require "Mod/KMLout.pm"; #my $kmlfile = Mod::KMLout::kmlGenerator($auth,""); }#end if $state =~ /canceled|occupied|available/ if($lock_state && $lock_state =~ /locking|locked|unlocking|unlocked/ && $record_pos->{cc_id} && $record_pos->{cc_id} > 0){ #content my $update_cc = { table => "content", mtime => "now()", owner => "$owner", }; #only by system=Ilockit if($record_pos->{int11} eq "2" && $q->param('voltage') && $q->param('voltage') =~ /(\d+)/){ $update_cc->{int14} = $1; $self->service_automatic($q) if($1 <= 50); } my $update_pos = { table => "contenttranspos", mtime => "now()", int24 => 0, }; $update_pos->{int14} = $q->escapeHTML($q->param('voltage')) if($q->param('voltage')); $update_pos->{txt21} = $q->escapeHTML($q->param('user_device')) if($q->param('user_device')); $update_pos->{txt26} = $q->escapeHTML($user_agent) if($user_agent); my $lock_value = 0; if($lock_state eq "locked"){ $lock_value = 1; $update_cc->{int20} = "$lock_value"; $update_pos->{int20} = "$lock_value"; $update_pos->{end_time} = "now()";#2021-01-10 set also end_time on locked ####### save locked GPS if available if($gps && $gps_age_minutes <= 3){ #geofencing for Ilockit my $geo_distance_next = $geo_distance; my $geo_debug=""; my ($stations,$stations_raw) = $self->stations_available($q,$varenv,$auth); foreach my $id (sort { $stations_raw->{$a}->{barcode} <=> $stations_raw->{$b}->{barcode} } keys (%$stations_raw)){ my $latitude_station = $1 if($stations_raw->{$id}->{txt06} =~ /^(\d+\.\d+)/); my $longitude_station = $1 if($stations_raw->{$id}->{txt06} =~ /(\d+\.\d+)$/); if(!looks_like_number($latitude) || !looks_like_number($longitude)){ $geo_debug .= "locked ERROR no user GPS: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; }elsif(looks_like_number($latitude) && looks_like_number($longitude) && looks_like_number($latitude_station) && looks_like_number($longitude_station)){ $geo_distance = $lb->geo_fencing($latitude,$longitude,$latitude_station,$longitude_station); $bw->log("geo_distance by geo_fencing:$latitude,$longitude,$latitude_station,$longitude_station|$stations_raw->{$id}->{txt06}",$geo_distance,""); if($geo_distance <= $stations_raw->{$id}->{int06}){ $geo_distance_next = $geo_distance; #end-Station $update_pos->{int04} = "$stations_raw->{$id}->{int04}"; $update_cc->{int04} = "$stations_raw->{$id}->{int04}"; $update_pos->{int24} = "1"; $geo_debug .= "locked Matching station: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; last; }else{ $geo_distance_next = $geo_distance if($geo_distance <= $geo_distance_next); $geo_debug .= "locked Out of station distance: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; } $update_pos->{txt06} = "$gps";#end pos coordinates $update_pos->{int21} = "$gps_age_minutes"; $update_pos->{int22} = "$gps_accuracy"; $update_pos->{int23} = "$geo_distance"; $update_cc->{txt06} = "$gps";#end content coordinates #end-Station prefix $update_pos->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}"; #end-Station prefix $update_cc->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}"; $rows = $dbt->update_record($dbh,$update_pos,$record_pos); }else{ $geo_debug .= "locked has no station GPS: $stations_raw->{$id}->{barcode}|$latitude,$longitude,$latitude_station,$longitude_station --> $geo_distance Meter\n"; } } $booking_values->{geo_distance} = "$geo_distance_next"; #print "$geo_debug\n"; $bw->log("locked GEOfencing geo_debug:$geo_debug",$booking_values->{geo_distance},""); } ######## end locke GPS if($state){ $booking_values->{response_state} .= " OK: bike " . $q->param('bike') . " locked confirmed"; $booking_values->{response_text} .= " Abschließen von Fahrrad Nr. " . $q->param('bike') . " bestätigt"; }else{ $booking_values->{response_state} = "OK: bike " . $q->param('bike') . " locked confirmed"; $booking_values->{response_text} = "Abschließen von Fahrrad Nr. " . $q->param('bike') . " bestätigt"; } }elsif($lock_state eq "unlocked"){ #int11=system >= 3 (sigo) with station_lock #int30=Station Id #int31=Slot Id #int27=velofactur bike Id if($record_cc->{int11} && $record_cc->{int11} >=3 && $record_cc->{int30} && $record_cc->{int31} && $record_cc->{int27}){ $bw->log("unlock station lock with: '$record_cc->{int30}' '$record_cc->{int31}' '$record_cc->{int27}' 'Freigeben' '$record_pos->{c_id}'","",""); #system(`$varenv{basedir}/src/scripts/velofaktur_client.pl $varenv{syshost} post_velo "$record_cc->{int30}" "$record_cc->{int31}" "$record_cc->{int27}" "Freigeben" "$record_pos->{c_id}"`); } $lock_value = 2; $update_cc->{int20} = "$lock_value"; $update_pos->{int20} = "$lock_value"; if($state){ $booking_values->{response_state} .= " OK: bike " . $q->param('bike') . " unlocked confirmed"; $booking_values->{response_text} .= " Aufschließen von Fahrrad Nr. " . $q->param('bike') . " bestätigt"; }else{ $booking_values->{response_state} = "OK: bike " . $q->param('bike') . " unlocked confirmed"; $booking_values->{response_text} = "Aufschließen von Fahrrad Nr. " . $q->param('bike') . " bestätigt"; } }elsif($lock_state eq "locking"){ $lock_value = 3; $update_cc->{int20} = "$lock_value"; $update_pos->{int20} = "$lock_value"; $update_pos->{int23} = "$geo_distance"; if($state){ $booking_values->{response_state} .= " OK: bike " . $q->param('bike') . " locking in progress"; $booking_values->{response_text} .= " Abschließen von Fahrrad Nr. " . $q->param('bike') . " ist im Prozess. Bitte warten bis das smartlock vollständig geschlossen wurde und das abschließen bestätigt wird."; }else{ $booking_values->{response_state} = "OK: bike " . $q->param('bike') . " locking in progress"; $booking_values->{response_text} = "Abschließen von Fahrrad Nr. " . $q->param('bike') . " ist im Prozess. Bitte warten bis das smartlock vollständig geschlossen wurde und das abschließen bestätigt wird."; } if($varenv{dbname} ne "sharee_lv" && !$record_pos->{int32}){ $bw->log("$varenv{basedir}/src/scripts/sms_message.pl $varenv{syshost} locking_progress $auth->{txt07} $record_pos->{c_id}",$record_pos->{c_id},""); system("$varenv{basedir}/src/scripts/sms_message.pl $varenv{syshost} locking_progress $auth->{txt07} $record_pos->{c_id} &"); } $update_pos->{int32} = $record_pos->{int32} + 1;#sms_message sent marker }elsif($lock_state eq "unlocking"){ $lock_value = 4; $update_cc->{int20} = "$lock_value"; $update_pos->{int20} = "$lock_value"; if($state){ $booking_values->{response_state} .= " OK: bike " . $q->param('bike') . " unlocking in progress"; $booking_values->{response_text} .= " Aufschließen von Fahrrad Nr. " . $q->param('bike') . " ist im Prozess."; }else{ $booking_values->{response_state} = "OK: bike " . $q->param('bike') . " unlocking in progress"; $booking_values->{response_text} = "Aufschließen von Fahrrad Nr. " . $q->param('bike') . " ist im Prozess."; } } $dbt->update_record($dbh,$update_pos,$record_pos); $dbt->update_record($dbh,$update_cc,$record_cc); }#end locked #fetch final booking state after request if($record_pos->{c_id} > 0){ my $booking_pos = { table => "contenttranspos", fetch => "one", c_id => "$record_pos->{c_id}", }; my $booking = $dbt->fetch_tablerecord($dbh,$booking_pos); if(ref($booking) eq "HASH" && $booking->{ct_name}){ #$booking_values->{bike} = "$booking->{ct_name}"; $booking_values->{bike} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}$booking->{barcode}"; $booking_values->{state} = "$dbt->{copri_conf}->{bike_state}->{$booking->{int10}}"; $booking_values->{lock_state} = "locked" if($booking->{int20} == 1); $booking_values->{lock_state} = "unlocked" if($booking->{int20} == 2); $booking_values->{lock_state} = "locking" if($booking->{int20} == 3); $booking_values->{lock_state} = "unlocking" if($booking->{int20} == 4); #fetch tracking distance on Ilockit cloud by summary trip if(tracking && deviceId && available) if($booking->{int25} == 1 && $booking->{int10} == 1){ sleep 2;#hopefully get distance in 2 sec. $bw->log("$varenv{basedir}/src/scripts/Ilockit_trackingcloud.pl $varenv{syshost} get_tripsum $booking->{c_id}",$booking->{c_id},""); #if ilockit clouid if($booking->{int13}){ system("$varenv{basedir}/src/scripts/Ilockit_trackingcloud.pl $varenv{syshost} get_tripsum $booking->{c_id}"); $booking = $dbt->fetch_tablerecord($dbh,$booking_pos); #try it again with 20sec sleep if(!$booking->{int26}){ $bw->log("$varenv{basedir}/src/scripts/Ilockit_trackingcloud.pl $varenv{syshost} get_tripsum $booking->{c_id} 20",$booking->{c_id},""); system("$varenv{basedir}/src/scripts/Ilockit_trackingcloud.pl $varenv{syshost} get_tripsum $booking->{c_id} 20 &"); $booking = $dbt->fetch_tablerecord($dbh,$booking_pos); } } my $co2saving = ""; #$booking->{int26} = 10 if(!$booking->{int26} && ($auth->{c_id} == 1842 || $auth->{c_id} == 5781 || $auth->{c_id} == 11765 || $auth->{c_id} == 1843));#10 km test if($booking->{int26}){ $co2saving = "Einsparung: "; my $co2diff = $pri->co2calc($booking); my $sprit_price = $pri->sprit2calc($booking); $co2saving .= "$co2diff kg CO2 und "; $co2saving .= "$sprit_price EUR "; $booking->{int26} =~ s/\./,/; $co2saving .= "bei einer Strecke von $booking->{int26} KM"; $booking_values->{co2saving} = $co2saving; } } #to LV only if available if($varenv{dbname} eq "sharee_lv" && $booking->{int10} == 1){ #system(`$varenv{basedir}/src/scripts/xml2lastenvelo.pl pos2xml $booking->{c_id} "contenttranspos" ""`); my $xml = "\n"; $xml .= "\n"; $xml .= "available\n"; $xml .= "$booking_values->{bike}\n"; $xml .= "$auth->{int01}\n"; $xml .= "$auth->{txt08}\n"; $xml .= "\n"; my $avail_file = "$varenv{xmlfile}/sharee_available.xml"; unlink "$avail_file"; open(FILE,">$avail_file"); print FILE "$xml"; close(FILE); chmod 0666, "$avail_file"; $bw->log("scp $avail_file",$xml,""); system("/usr/bin/scp -P 50001 $avail_file pi\@localhost:/home/pi/lvfserver/inbox_xml_files/.") if($dbt->{copri_conf}->{stage} eq "live"); } } } return ($rows,$booking_values); } #end booking_update # # #dedicated service insert automatic sub service_automatic { my $self = shift; my $q = shift || ""; my $station_id = ""; my $bike_id = ""; $station_id = $1 if($q->param('station') =~ /(\d+)/);#could be also 0 $bike_id = $1 if($q->param('bike') && $q->param('bike') =~ /(\d+)/); my $authraw = { c_id => $owner };#default sys API my $lock_charge = "Achtung, Fahrradschloss Ladung unter " . $q->param('voltage') . "%"; my $response = {}; if(looks_like_number($bike_id) || looks_like_number($station_id)){ $q->param(-name=>'request',-value=>"service_done"); $q->param(-name=>'work_id',-value=>"txt01"); $q->param(-name=>'work_val',-value=>"$lock_charge"); my $article = looks_like_number($bike_id) || looks_like_number($station_id); (my $xresponse->{$article}, my $responseraw, my $node_template, my $crecord) = $self->service_select($q,$authraw,"","1"); if(ref($xresponse->{$article}) ne "HASH" || !$xresponse->{$article}->{c_id}){ ($response->{service_id}) = $self->service_insert($q,$authraw,$node_template,$crecord); $bw->log("service_automatic insert ($xresponse->{$article}->{c_id}) ",$response,""); my $rows = $self->service_update($q,$authraw,$node_template,$response->{service_id}); } } } #user rentals_history sub user_rentals_history(){ my $self = shift; my $q = shift || ""; my $auth = shift; my %varenv = $cf->envonline(); my $record_all = {}; my $pref = { table => "contenttrans", table_pos => "contenttranspos", fetch => "all", keyfield => "c_id", ca_id => "$auth->{c_id}", }; if(looks_like_number($q->param('month')) && $q->param('month') > 0){ my $month = $q->param('month'); $pref->{mtime} = ">=::(now() - interval '$month month')"; }else{ #2021-06-18, list only postions which are not invoiced (Form Buchungsdaten) #$pref->{close_time} = "is::null"; $pref->{'ct.state'} = "is::null"; $pref->{'ct.int14'} = "is::null"; } my %operator_hash = (); if($varenv{dbname} eq "sharee_primary"){ if($auth->{txt17}){ if($auth->{txt17} =~ /\w\s\w/){ %operator_hash = map { $_ => "$dbt->{operator}{$_}->{operatorApp}" } split(/\s+/,$auth->{txt17}); }else{ $operator_hash{$auth->{txt17}} = "$dbt->{operator}{$auth->{txt17}}->{operatorApp}"; } foreach my $sharee_operator (keys (%operator_hash)){ my $dbh_operator = $dbt->dbconnect_extern("$sharee_operator"); my $record = $dbt->collect_post($dbh_operator,$pref); $record_all = { %$record_all, %$record }; } } }else{ $record_all = $dbt->collect_post($dbh,$pref); } return ($record_all,\%operator_hash); }#end user_rental_history #user bikes occupied sub user_bikes_occupied(){ my $self = shift; my $q = shift; my $auth = shift; my $pref = { table => "contenttrans", table_pos => "contenttranspos", fetch => "all", template_id => "218",#Faktura tpl_id keyfield => "c_id", ca_id => "$auth->{c_id}", #txt10 => "IN::('occupied','requested')", int10 => "IN::('3','2')", "ct.close_time" => "is::null", }; my $record = $dbt->collect_post($dbh,$pref); return $record; }#end user_bikes_occupied #rentals #called by user_bikes_occupied (bikes_occupied object) sub rentals(){ my $self = shift; my $record = shift; my $auth = shift || ""; my $withkey = shift || 0; my %varenv = $cf->envonline(); my $today4db = strftime("%Y-%m-%d %H:%M:%S",localtime(time)); my $return = {}; foreach my $id (sort { $record->{$a}->{end_time} cmp $record->{$b}->{end_time} } keys (%$record)){ #last #$return->{$id} = $pri->sharee_pricing($record->{$id},"readonly"); #new sharee_pricing (my $return_counting->{$id}, my $counting) = $pri->counting_rental(\%varenv,$record->{$id},"readonly"); my $return_feed->{$id} = $pri->fetch_rentalfeed(\%varenv,$record->{$id},$return_counting->{$id}); $return->{$id} = { %{ $return_counting->{$id} }, %{ $return_feed->{$id} } }; my $bike_id = $return->{$id}->{bike}; $bike_id = $1 if($bike_id =~ /(\d+)/); #generate always new ilockit keys. if($withkey && $record->{$id}->{int11} && $record->{$id}->{int11} == 2){ my @K_select = (); @K_select = `cd /var/www/copri4/main/src/scripts && export CLASSPATH='.:/usr/share/java:/usr/share/java/postgresql.jar' && java Ilockauth $varenv{dbname} $bike_id`; $bw->log("rentals java Ilockauth $bike_id | syshost:$varenv{syshost}",\@K_select,""); foreach(@K_select){ my ($K_key,$K_val) = split(/ = /, $_); $K_val =~ s/\n//g; $return->{$id}->{K_seed} = "$K_val" if($K_key eq "K_seed"); $return->{$id}->{K_a} = "$K_val" if($K_key eq "K_a" && $auth->{int19} && $auth->{int19} == 1); $return->{$id}->{K_u} = "$K_val" if($K_key eq "K_u"); } } } return $return; }#end rentals #bikes_available sub bikes_available(){ my $self = shift; my $q = shift; my $varenv = shift; my $auth = shift; my $authed = 0; my $station = $q->escapeHTML($q->param('station')) || ""; my $station_id = $1 if($station =~ /(\d+)/); my $bike = $q->escapeHTML($q->param('bike')) || ""; my $bike_id = $bike; $bike_id =~ s/S[1-9]X/SX/; $bike_id = $1 if($bike_id =~ /(\d+)/); #my $users_serviceapp = $dbt->select_users($dbh,$auth->{c_id},"and int09=1"); my $return={}; my $pref = { table => "content", fetch => "all", keyfield => "barcode", template_id => "205", int10 => "1",#1 = "available" }; my $tariff_content = {}; $authed = 1 if(ref($auth) eq "HASH" && $auth->{c_id} > 0); (my $bike_group,my $user_group,$tariff_content,my $user_tour) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie')); my $main_ids = join(",",@{$bike_group}); $main_ids =~ s/[a-z_-]+//ig;#should work also without Trenner $pref = { %$pref, main_id => "IN::($main_ids)" }; if(looks_like_number($station_id)){ $pref = { %$pref, int04 => "=::" . $station_id }; } if(looks_like_number($bike_id)){ $pref = { %$pref, barcode => "=::" . $bike_id }; } my $record = $dbt->fetch_record($dbh,$pref) if(ref($bike_group) eq "ARRAY" && @{$bike_group}[0]); my $op_return = {}; my @adr_tariff = (); if($auth->{txt30}){ @adr_tariff = ("$auth->{txt30}"); @adr_tariff = split(/\s+/,$auth->{txt30}) if($auth->{txt30} =~ /\w\s+\w/); }elsif(ref($tariff_content) eq "HASH"){ foreach my $tid (keys (%$tariff_content)){ push(@adr_tariff, "$tariff_content->{$tid}->{barcode}") if($tariff_content->{$tid}->{int18} eq 2); } } my $td_template = $dbt->rental_description_template(); foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ $return->{$id}->{authed} = "$authed"; $return->{$id}->{station} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{int04}"; $return->{$id}->{uri_operator} = "$varenv->{wwwhost}"; ($return->{$id}->{gps}->{latitude},$return->{$id}->{gps}->{longitude}) = split(/,/,$record->{$id}->{txt06}); $return->{$id}->{bike} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{barcode}"; #$return->{$id}->{description} = "$record->{$id}->{txt01}"; $return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $record->{$id}->{txt01})); $return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}"; $return->{$id}->{bike_charge} = "$record->{$id}->{int19}" if($record->{$id}->{int19}); $return->{$id}->{lock_state} = "locked" if($record->{$id}->{int20} == 1); $return->{$id}->{lock_state} = "unlocked" if($record->{$id}->{int20} == 2); $return->{$id}->{lock_state} = "locking" if($record->{$id}->{int20} == 3); $return->{$id}->{lock_state} = "unlocking" if($record->{$id}->{int20} == 4); $return->{$id}->{bike_group} = ["$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{main_id}"]; if($record->{$id}->{int11} eq "2"){ $return->{$id}->{system} = "Ilockit"; $return->{$id}->{Ilockit_GUID} = "$record->{$id}->{txt17}"; $return->{$id}->{Ilockit_ID} = "$record->{$id}->{txt18}"; #if($users_serviceapp->{int09}) #shareetool if($q->param('authcookie') && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} == 187 && scalar(@{$user_tour} >= 1)){ my @service_code = split(/\s/,$record->{$id}->{txt23}); $return->{$id}->{service_code} = [@service_code]; } }elsif($record->{$id}->{int11} eq "3"){ $return->{$id}->{system} = "sigo"; } if(ref($tariff_content) eq "HASH"){ foreach my $tid (sort { $tariff_content->{$a}->{barcode} <=> $tariff_content->{$b}->{barcode} } keys (%$tariff_content)){ #$bw->log("bikes_available tariff_content tariff_description $tariff_content->{$tid}->{int12} && $auth->{txt30} =~ /$tariff_content->{$tid}->{barcode}/ BIKE:",$return->{$id}->{bike},""); foreach(@adr_tariff){ if($record->{$id}->{main_id} == $tariff_content->{$tid}->{int12} && $_ == $tariff_content->{$tid}->{barcode}){ $bw->log("bikes_available for user c_id: $auth->{c_id} if($record->{$id}->{main_id} == $tariff_content->{$tid}->{int12} && $_ == $tariff_content->{$tid}->{barcode}) on BIKE:",$return->{$id}->{bike},""); #deprecated $return->{$id}->{tariff_description}->{name} = "$tariff_content->{$tid}->{ct_name}"; $return->{$id}->{tariff_description}->{number} = "$tariff_content->{$tid}->{barcode}"; $return->{$id}->{tariff_description}->{eur_per_hour} = "$tariff_content->{$tid}->{int02}" || "0"; $return->{$id}->{tariff_description}->{max_eur_per_day} = "$tariff_content->{$tid}->{int17}" if($tariff_content->{$tid}->{int17}); $return->{$id}->{tariff_description}->{free_hours} = "$tariff_content->{$tid}->{int16}" if($tariff_content->{$tid}->{int16}); $return->{$id}->{tariff_description}->{abo_eur_per_month} = "$tariff_content->{$tid}->{int15}" if($tariff_content->{$tid}->{int15}); #TODO, have to be set on Tarif table $return->{$id}->{tariff_description}->{operator_agb} = "Mit der Mietrad Anmietung wird folgender Betreiber AGB zugestimmt (als Demo sharee AGB)." if($auth->{c_id} && ($auth->{c_id} == 1842 || $auth->{c_id} == 5781 || $auth->{c_id} == 22262)); #new rental_description $return->{$id}->{rental_description}->{name} = "$tariff_content->{$tid}->{ct_name}"; $return->{$id}->{rental_description}->{id} = "$tariff_content->{$tid}->{barcode}"; $return->{$id}->{rental_description}->{rental_info}->{1} = ["Tracking","Ich stimme der Speicherung (Tracking) meiner Fahrstrecke zwecks wissenschaftlicher Auswertung und Berechnung der CO2-Einsparung zu!"] if($record->{$id}->{int25}); $return->{$id}->{rental_description}->{rental_info}->{2} = ["AGB","Mit der Mietrad Anmietung wird folgender Betreiber AGB zugestimmt (als Demo sharee AGB)."] if($auth->{c_id} && ($auth->{c_id} == 1842 || $auth->{c_id} == 5781 || $auth->{c_id} == 22262)); my $i = 0; foreach my $td (sort keys (%$td_template)){ my $time_unit = ""; if($td_template->{$td}->{int35} && $tariff_content->{$tid}->{int35} && $tariff_content->{$tid}->{int35} > 0){ $tariff_content->{$tid}->{int35} =~ s/\./,/; $time_unit = $dbt->time_format($tariff_content->{$tid}->{time01}); $return->{$id}->{rental_description}->{tarif_elements}->{$td} = ["$td_template->{$td}->{int35}","$tariff_content->{$tid}->{int35} € / $time_unit"]; }elsif($td_template->{$td}->{int36} && $tariff_content->{$tid}->{int36} && $tariff_content->{$tid}->{int36} > 0){ $tariff_content->{$tid}->{int36} =~ s/\./,/; $time_unit = $dbt->time_format($tariff_content->{$tid}->{time01}); $return->{$id}->{rental_description}->{tarif_elements}->{$td} = ["$td_template->{$td}->{int36}", "$tariff_content->{$tid}->{int36} € / $time_unit"]; }elsif($td_template->{$td}->{int17} && $tariff_content->{$tid}->{int17} && $tariff_content->{$tid}->{int17} > 0){ #$tariff_content->{$tid}->{int17} =~ s/\./,/; $return->{$id}->{rental_description}->{tarif_elements}->{$td} = ["$td_template->{$td}->{int17}","$tariff_content->{$tid}->{int17} € / Tag"]; }elsif($td_template->{$td}->{time02} && $tariff_content->{$tid}->{time02} =~ /[1-9]/){ $time_unit = $dbt->time_format($tariff_content->{$tid}->{time02}); $return->{$id}->{rental_description}->{tarif_elements}->{$td} = ["$td_template->{$td}->{time02}","$time_unit / Tag"]; } }#end new rental_description } } } } $op_return->{$dbt->{operator}->{$varenv->{dbname}}->{oprefix} . $id} = $return->{$id}; } return $op_return; }#end bikes_available #bikes_all sub bikes_all(){ my $self = shift; my $q = shift; my $varenv = shift; my $auth = shift || {}; my $stations_allraw = shift || ""; #my $users_serviceapp = $dbt->select_users($dbh,$auth->{c_id},"and int09=1"); my $return={}; my $pref = { table => "content", fetch => "all", keyfield => "barcode",#2018-02-21 changed to bike id template_id => "205",#Leihrad_liste int10 => "!=::3", }; my ($bike_group,$user_group,$tariff_content,$user_tour) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie')); my $main_ids = join(",",@{$bike_group}); $main_ids =~ s/[a-z_]+//ig; $pref = { %$pref, main_id => "IN::($main_ids)" }; my $station_id = ""; my $bike_id = ""; #$station_id = $1 if($q->param('station') && $q->param('station') =~ /(\d+)/);#doesn't get 0 $station_id = $1 if($q->param('station') =~ /(\d+)/); $bike_id = $1 if($q->param('bike') && $q->param('bike') =~ /(\d+)/); $pref->{int04} = "=::$station_id" if(looks_like_number($station_id)); $pref->{ barcode} = "=::$bike_id" if(looks_like_number($bike_id)); my $record = {}; #on servicetool only stations on user_tour $bw->log("stations_service_tour of adr c_id: $auth->{c_id}",$stations_allraw,""); my @stations_service_tour = (); #shareetool if(!$pref->{int04} && $q->param('authcookie') && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} == 187){ my $stations = ""; if(ref($stations_allraw) eq "HASH" && scalar(@{$user_tour} >= 1)){ foreach my $id (sort { $stations_allraw->{$a}->{int04} <=> $stations_allraw->{$b}->{int04} } keys (%$stations_allraw)){ push(@stations_service_tour, $stations_allraw->{$id}->{int04}) if(looks_like_number($stations_allraw->{$id}->{int04})); } $stations = join(",",@stations_service_tour); $stations =~ s/[a-z_]+//ig; $pref->{int04} = "IN::($stations)" if($stations || $stations eq "0"); } } $bw->log("sub bikes_all with user_tour ($station_id) @stations_service_tour",$pref,""); $record = $dbt->fetch_record($dbh,$pref) if(ref($bike_group) eq "ARRAY" && @{$bike_group}[0]); my $bikes_on_station = {}; my $op_return = {}; foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ if(1==1){ $bikes_on_station->{$record->{$id}->{int04}}->{bike_ist} += 1; $return->{$id}->{uri_operator} = "$varenv->{wwwhost}"; $return->{$id}->{station} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{int04}"; ($return->{$id}->{gps}->{latitude},$return->{$id}->{gps}->{longitude}) = split(/,/,$record->{$id}->{txt06}); $return->{$id}->{bike} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{barcode}"; #$return->{$id}->{description} = "$record->{$id}->{txt01}"; $return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $record->{$id}->{txt01})); $return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}"; $return->{$id}->{service_state} = "0"; $return->{$id}->{lock_state} = "locked" if($record->{$id}->{int20} == 1); $return->{$id}->{lock_state} = "unlocked" if($record->{$id}->{int20} == 2); $return->{$id}->{lock_state} = "locking" if($record->{$id}->{int20} == 3); $return->{$id}->{lock_state} = "unlocking" if($record->{$id}->{int20} == 4); $return->{$id}->{bike_group} = ["$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{main_id}"]; if($record->{$id}->{int11} eq "2"){ $return->{$id}->{system} = "Ilockit"; $return->{$id}->{Ilockit_GUID} = "$record->{$id}->{txt17}"; $return->{$id}->{Ilockit_ID} = "$record->{$id}->{txt18}"; #shareetool if($q->param('authcookie') && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} == 187 && scalar(@{$user_tour} >= 1)){ my @service_code = split(/\s/,$record->{$id}->{txt23}); $return->{$id}->{service_code} = [@service_code]; } }elsif($record->{$id}->{int11} eq "3"){ $return->{$id}->{system} = "sigo"; } $op_return->{$dbt->{operator}->{$varenv->{dbname}}->{oprefix} . $id} = $return->{$id}; } } return ($op_return,$record,$bikes_on_station); }#end bikes_all #stations_available sub stations_available(){ my $self = shift; my $q = shift || ""; my $varenv = shift; my $auth = shift || ""; my $authed = 0; $authed = 1 if(ref($auth) eq "HASH" && $auth->{c_id}); my ($bike_group,$user_group,$tariff_content,$user_tour) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie')); my $return = {}; my $pref = { table => "content", fetch => "all", keyfield => "int04", template_id => "225", int10 => "1",#1 = "available" }; my $pref_sql = ""; $pref_sql .= " and ("; foreach(@{$bike_group}){ if($_ =~ /(\d+)/){ $pref_sql .= " ct.txt24 like '%$1%' OR"; } } $pref_sql =~ s/OR$//; $pref_sql .= ")"; $pref_sql = "" if($pref_sql !~ /\d/); my $record = {}; $record = $dbt->fetch_record($dbh,$pref,$pref_sql) if(ref($bike_group) eq "ARRAY" && @{$bike_group}[0]); my $op_return = {}; foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ $return->{$id}->{authed} = "$authed"; $return->{$id}->{station} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{int04}"; $return->{$id}->{uri_operator} = "$varenv->{wwwhost}"; ($return->{$id}->{gps}->{latitude},$return->{$id}->{gps}->{longitude}) = split(/,/,$record->{$id}->{txt06}); #$return->{$id}->{description} = "$record->{$id}->{txt01}"; $return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $record->{$id}->{txt01})); $return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}"; $return->{$id}->{station_group} = ""; if($record->{$id}->{txt24}){#Ilockit with new station_group logic $return->{$id}->{gps_radius} = "$record->{$id}->{int06}"; $record->{$id}->{txt24} =~ s/(\d+)/$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$1/g; my @station_group = split(/\s/,$record->{$id}->{txt24}); $return->{$id}->{station_group} = [@station_group]; } my $hotline_hash = { table => "contentuser", fetch => "one", template_id => 197, c_id => "1", }; my $hotline_data = $dbt->fetch_record($dbh,$hotline_hash); $return->{$id}->{operator_data} = { "operator_name" => "", "operator_hours" => "", "operator_color" => "", "operator_logo" => "", "operator_phone" => "", "operator_email" => "", }; $return->{$id}->{operator_data}->{operator_name} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$hotline_data->{txt01})) if($hotline_data->{txt01}); $return->{$id}->{operator_data}->{operator_hours} = Encode::encode('utf-8', Encode::decode('iso-8859-1',$hotline_data->{txt84})) if($hotline_data->{txt84}); $return->{$id}->{operator_data}->{operator_color} = $hotline_data->{txt85} if($hotline_data->{txt85}); $return->{$id}->{operator_data}->{operator_logo} = $hotline_data->{img01} if($hotline_data->{img01}); $return->{$id}->{operator_data}->{operator_phone} = $hotline_data->{txt07} if($hotline_data->{txt07}); $return->{$id}->{operator_data}->{operator_email} = $hotline_data->{txt08} if($hotline_data->{txt08}); $op_return->{$dbt->{operator}->{$varenv->{dbname}}->{oprefix} . $id} = $return->{$id}; } return ($op_return, $record); }#end stations_available #stations_all (should only called by shareetool) sub stations_all(){ my $self = shift; my $q = shift || ""; my $varenv = shift; my $bikes_on_station = shift || {}; my $auth = shift || ""; my $authed = 0; $authed = 1 if(ref($auth) eq "HASH" && $auth->{c_id}); my ($bike_group,$user_group,$tariff_content,$user_tour) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie')); my $return={}; my $pref = { table => "content", fetch => "all", keyfield => "int04", template_id => "225",#Station_liste }; my $station_id = ""; my $work_val_id = ""; $station_id = $1 if($q->param('station') =~ /(\d+)/);#could be also 0 $work_val_id = $1 if($q->param('work_val') && $q->param('work_val') =~ /(\d+)/); if(looks_like_number($station_id)){ $pref->{int04} = "=::$station_id"; }elsif($q->param('work_id') && $q->param('work_id') eq "int04" && $work_val_id){ $pref->{int04} = "=::$work_val_id"; } #if not shareetool then only available stations $pref->{int10} = 1 if(!$q->param('authcookie') || !$varenv->{merchant_id} || !$dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} || $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} != 187); my $pref_sql = ""; $pref_sql .= " and ("; foreach(@{$bike_group}){ if($_ =~ /(\d+)/){ $pref_sql .= " ct.txt24 like '%$1%' OR"; } } $pref_sql =~ s/OR$//; $pref_sql .= ")"; $pref_sql = "" if($pref_sql !~ /\d/); my $record = {}; my $op_return = {}; my %user_tour = (); #on servicetool only stations on user_tour #shareetool $bw->log("stations user_tour by merchant id $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} on $varenv->{dbname}",$user_tour,""); if($q->param('authcookie') && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} && $dbt->{merchant_ids}->{$varenv->{merchant_id}}->{id} == 187){ if(scalar(@{$user_tour}) >= 1){ $pref_sql .= " AND ("; foreach(@{$user_tour}){ if($_ =~ /(\d+)/){ #$pref_sql .= " ct.int07=$1 OR"; $user_tour{$1} = 1; $pref_sql .= " ct.txt07 like '%$1%' OR"; } } $pref_sql =~ s/OR$//; $pref_sql .= ")"; $record = $dbt->fetch_record($dbh,$pref,$pref_sql) if(ref($bike_group) eq "ARRAY" && @{$bike_group}[0]); } } #only nececarry if amount of available bikes lower then bike_soll (like konrad) #my $bike_ist_factor = 1; #$bike_ist_factor = $self->bikes_soll($record,$bikes_on_station); #$bike_ist_factor = 1 if($bike_ist_factor > 1); foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ my $bike_soll = $record->{$id}->{int05} || 0;# * $bike_ist_factor; #$bike_soll = $lb->round_half($bike_soll); #$bike_soll =~ s/\.\d+//;#rounded integer $return->{$id}->{authed} = "$authed"; $return->{$id}->{station} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{int04}"; $return->{$id}->{service_tour} = ""; #hashed because of one station can have multi station tour #there is a restriction in servicetool because of service_tour assignment (can keep only one value) #keep in mind to select only users user_tour which in service_tour, #because there can only one station assignmemt. Should be array, also in shareetool! my %station_tour = (); if($record->{$id}->{txt07} && $record->{$id}->{txt07} =~ /\d\s\d/){ %station_tour = map { $_ => 1 } split(/\s+/,$record->{$id}->{txt07}); }elsif($record->{$id}->{txt07}){ $station_tour{$record->{$id}->{txt07}} = 1; } #if multi station tour defined then last numerical will assigend foreach my $stour (sort { $a <=> $b }keys (%user_tour)){ if($station_tour{$stour}){ $return->{$id}->{service_tour} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$stour"; } } $return->{$id}->{uri_operator} = "$varenv->{wwwhost}"; ($return->{$id}->{gps}->{latitude},$return->{$id}->{gps}->{longitude}) = split(/,/,$record->{$id}->{txt06}); if($return->{$id}->{description}){ $return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $record->{$id}->{txt01})); }else{ $return->{$id}->{description} = "---"; } $return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}"; $return->{$id}->{bike_soll} = "$bike_soll" || "0"; $return->{$id}->{bike_ist} = "$bikes_on_station->{$id}->{bike_ist}" || "0"; $return->{$id}->{station_group} = ""; if($record->{$id}->{txt24}){#sharee Ilockit with new station_group logic $return->{$id}->{gps_radius} = "$record->{$id}->{int06}"; $record->{$id}->{txt24} =~ s/(\d+)/$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$1/g; my @station_group = split(/\s/,$record->{$id}->{txt24}); $return->{$id}->{station_group} = [@station_group]; } $op_return->{$dbt->{operator}->{$varenv->{dbname}}->{oprefix} . $id} = $return->{$id}; } return ($op_return,$record); }#end stations_all #collect all bike_ist sub bikes_soll(){ my $self = shift; my $record = shift; my $bikes_on_station = shift; my $bike_soll_all = 0; foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){ $bike_soll_all += $record->{$id}->{int05}; } #my $bikes_on_station_ist->{bikes_all} = '0'; my $bikes_on_station_ist->{bikes_all_onstation} = '0'; if(ref($bikes_on_station) eq "HASH"){ foreach my $st (keys(%$bikes_on_station)){ #$bikes_on_station_ist->{bikes_all} += $bikes_on_station->{$st}->{bike_ist};#incl st.0 $bikes_on_station_ist->{bikes_all_onstation} += $bikes_on_station->{$st}->{bike_ist} if($st > 0); } } my $bike_ist_factor = 1; if(looks_like_number($bikes_on_station_ist->{bikes_all_onstation}) && $bikes_on_station_ist->{bikes_all_onstation} > 0 && looks_like_number($bike_soll_all) && $bike_soll_all > 0){ $bike_ist_factor = sprintf('%.2f',$bikes_on_station_ist->{bikes_all_onstation} / $bike_soll_all); } return $bike_ist_factor; } #Collect Tariff to get user_group---------------------- sub fetch_tariff(){ my $self = shift; my $dbname = shift; my $adr = shift || {}; my $authcookie = shift || ""; my $merchant_id = ""; $merchant_id = $1 if($authcookie && $authcookie =~ /\w+_(\w+)$/); my $tariff_content = {}; my @user_tour = (); my $auth_operator = {}; #int18 # # 2 = "public" # 3 = "private" # 4 = "hidden-lv" # 5 = "public-bonus" # my $tariff = { table => "content", fetch => "all", keyfield => "barcode", template_id => "210",#Tariff tpl_id }; #if no primary address then only 2=public if((ref($adr) ne "HASH" || !$adr->{c_id}) && ($dbname ne "sharee_lv")){ $tariff->{int18} = 2; $tariff_content = $dbt->fetch_record($dbh,$tariff); $bw->log("1. Tariff type $tariff->{int18} select on",$dbname,""); }elsif(ref($adr) eq "HASH" && $adr->{c_id}){ #select operators address to get users tarifnr array in txt30 delete $tariff->{int18} if($tariff->{int18}); my $authref = { table => "contentadr", fetch => "one", template_id => "202", c_id => "=::$adr->{c_id}", }; $auth_operator = $dbt->fetch_record($dbh,$authref); #shareetool if($merchant_id && $dbt->{merchant_ids}->{$merchant_id}->{id} && $dbt->{merchant_ids}->{$merchant_id}->{id} == 187){ my $users_serviceapp = $dbt->select_users($dbh,$auth_operator->{c_id},"and int09=1"); if($users_serviceapp->{int09}){ $auth_operator->{txt18} =~ s/(\d+)/$dbt->{operator}->{$dbname}->{oprefix}$1/g; @user_tour = ($auth_operator->{txt18}); @user_tour = split(/\s/,$auth_operator->{txt18}) if($auth_operator->{txt18} =~ /\s/); } } #$tariff->{int18} = 2;#disabled because wee need all $tariff->{int18} = 4 if($dbname eq "sharee_lv"); #FIXME user tarif select have to be fetched like in net_booking #$tariff_content must contain tariff_description in App bikes_available listing $tariff_content = $dbt->fetch_record($dbh,$tariff); $bw->log("2. Tariff type $tariff->{int18} select on",$dbname,""); # }else{ $bw->log("3. NO tariff_content on",$dbname,""); } my $oprefix = ""; $oprefix = "$dbt->{operator}->{$dbname}->{oprefix}" if($dbt->{operator}->{$dbname}->{oprefix}); my @tarifnr = (); my @user_group = (); my @bike_group = (); my @adr_tariff = (); if($auth_operator->{txt30}){ @adr_tariff = ("$auth_operator->{txt30}"); @adr_tariff = split(/\s+/,$auth_operator->{txt30}) if($auth_operator->{txt30} =~ /\w\s+\w/); } foreach my $id (keys (%$tariff_content)){ $bw->log("Tarif searching for authorized user-id $auth_operator->{c_id} by: if($auth_operator->{txt30} && $auth_operator->{txt30} =~ /$tariff_content->{$id}->{barcode}/ && $tariff_content->{$id}->{int12}) (s-type:$tariff_content->{$id}->{int18})","",""); foreach(@adr_tariff){ if($_ == $tariff_content->{$id}->{barcode} && $tariff_content->{$id}->{int12}){ $bw->log("Tarif FOUND with merchant $merchant_id for authorized user-id $auth_operator->{c_id} if($tariff_content->{$id}->{int12}) (s-type:$tariff_content->{$id}->{int18})",$tariff_content->{$id}->{barcode},""); push(@tarifnr, "$tariff_content->{$id}->{barcode}"); push(@user_group, "$oprefix$tariff_content->{$id}->{int12}");#sharee bike_node.main_id push(@bike_group, "$oprefix$tariff_content->{$id}->{int12}");#sharee bike_node.main_id } } } #fallback to public tarif if no user tariff defined and not servicetool app request #shareetool if(!@tarifnr && (!$dbt->{merchant_ids}->{$merchant_id}->{id} || $dbt->{merchant_ids}->{$merchant_id}->{id} != 187)){ foreach my $id (keys (%$tariff_content)){ if($tariff_content->{$id}->{int18} eq 2){ $bw->log("Tarif FOUND FALLBACK for No Tarif users with merchant $merchant_id if($tariff_content->{$id}->{int12} && $dbname) (s-type:$tariff_content->{$id}->{int18})",$id,""); push(@tarifnr, "$tariff_content->{$id}->{barcode}"); push(@user_group, "$oprefix$tariff_content->{$id}->{int12}");#sharee bike_node.main_id push(@bike_group, "$oprefix$tariff_content->{$id}->{int12}");#sharee bike_node.main_id } } } $bw->log("FETCHED_Tarif by dbname:$dbname with merchant $merchant_id | user_group:@user_group | bike_group:@bike_group | user_tour:@user_tour | tarifnr: @tarifnr",\@tarifnr,""); return (\@bike_group,\@user_group,$tariff_content,\@user_tour); } #authout sub authout(){ my $self = shift; my $q = shift; my $coo = shift || ""; my %varenv = $cf->envonline(); my $dbh = ""; my $record = { c_id => 0 };#if fails my $return = { authcookie => "" };#if fails my $cgi_authcookie = $q->param('authcookie') || $coo || ""; $bw->log("authout coo:$cgi_authcookie",$q,""); if($cgi_authcookie && length($cgi_authcookie) > 20){ my $authref = { table => "contentadr", fetch => "one", #keyfield => "c_id", template_id => "202", txt05 => "like::" . "%" . $q->escapeHTML($cgi_authcookie) . "%", }; $record = $dbt->fetch_record($dbh,$authref); my @user_group = (); if ($record->{c_id} > 0 && length($record->{txt05}) > 20){ my $all_authcookie = $record->{txt05}; my @check_cookies = split(/\|/,$record->{txt05}); foreach(@check_cookies){ #if(length($_) > 20 && $_ eq $cgi_authcookie){ if(length($_) > 20 && $_ =~ /$cgi_authcookie/){ $return = { authcookie => $_ }; $all_authcookie =~ s/$_//g;#delete authcookie if available $all_authcookie =~ s/\|$//; $all_authcookie =~ s/\|\|/\|/g; my $update = { table => "contentadr", txt05 => $all_authcookie, }; #print Dumper($update); my $rows = 0; $rows = $dbt->update_record($dbh,$update,$record); if($varenv{dbname} ne "sharee_primary"){ my $dbh_prim = $dbt->dbconnect_extern("sharee_primary"); $rows = $dbt->update_record($dbh_prim,$update,$record); } if($rows == 1){ $return = { authcookie => "1", user_id => "$record->{txt08}", user_group => @user_group, }; $return = { %$return, debuglevel => "$record->{int11}" } if($record->{int11}); $return = { %$return, Ilockit_admin => "$record->{int19}" } if($record->{int19}); } } } } } return $return; }#end authout #auth_verify sub auth_verify(){ my $self = shift; my $q = shift; my $coo = shift || ""; my $userc_id = shift || ""; my $new_authcoo = shift || ""; my $cgi_authcookie = $q->param('authcookie') || $q->param('sessionid') || $coo; my $session_log = $q->param('sessionid') || ""; my $user_agent = $q->user_agent(); my $clientIP = $q->remote_addr(); my %varenv = (); $varenv{dbname} = ""; %varenv = $cf->envonline(); my $record = { c_id => 0 };#if fails my $return = { authcookie => "", merchant_id => "", user_tour => [], user_group => [] }; my $user_group = ""; my $bike_group = ""; my $tariff_content = ""; my $user_tour = ""; $return->{merchant_id} = $1 if($cgi_authcookie && $cgi_authcookie =~ /\w+_(\w+)$/); my $netloc = $q->url(-base=>1); $bw->log("--> auth_verify on dbname $varenv{dbname},\n Starting with authcookie: $cgi_authcookie",$netloc,""); my $debug=1; my $now_dt = strftime "%Y-%m-%d %H:%M:%S", localtime; open(FILE,">>$varenv{logdir}/authcookie.log") if($debug); print FILE "\n*-->$now_dt $netloc | $varenv{dbname} | $cgi_authcookie\n" if($debug); if($cgi_authcookie && length($cgi_authcookie) > 30){ my $authref = { table => "contentadr", fetch => "one", template_id => "202", txt05 => "like::" . "%" . $q->escapeHTML($cgi_authcookie) . "%", }; my $auth_primary = { c_id => 0 }; my $auth_operator = { c_id => 0 }; $auth_operator = $dbt->fetch_record($dbh,$authref); $bw->log("auth_verified on operator $varenv{dbname} anchor 1",$auth_operator->{c_id},""); #just part of operator-routing (sharee account management) if($varenv{dbname} ne "sharee_primary"){ #primary select my $dbh_primary = $dbt->dbconnect_extern("sharee_primary"); $auth_primary = $dbt->fetch_record($dbh_primary,$authref); if($auth_primary->{c_id} && $auth_primary->{c_id} > 0){ $bw->log("auth_verified on primary anchor 2 by dbname $varenv{dbname}",$auth_primary->{c_id},""); print FILE "auth_verified on primary anchor 2 by dbname $varenv{dbname} | pri $auth_primary->{c_id}\n if($debug)"; #On booking_request, user must be authenticated and addr must exist #At first insert/update Operator dbname array on primary if($q->param('request') && $q->param('request') eq "booking_request"){ #first, save operator array which are used my %operator_hash = ();#local DB $bw->log("booking_request auth_verified by dbname $varenv{dbname}",$auth_primary->{c_id},""); print FILE "booking_request auth_verified by dbname $varenv{dbname} | pri $auth_primary->{c_id}\n if($debug)"; if($auth_primary->{txt17} && $auth_primary->{txt17} =~ /\w\s\w/){#append DB's %operator_hash = map { $_ => 1 } split(/\s+/,$auth_primary->{txt17}); }elsif($auth_primary->{txt17}){ $operator_hash{$auth_primary->{txt17}} = 1; } $operator_hash{$varenv{dbname}} = 1 if($varenv{dbname} ne "sharee_lv");#LastenVelo dbname will be only set by xml my @operator_array = keys %operator_hash; $bw->log("auth_verified update operator keys by array: @operator_array",\%operator_hash,""); print FILE "auth_verified update operator keys by array: @operator_array | pri $auth_primary->{c_id}\n" if($debug); my $update_primary = { table => "contentadr", txt17 => "@operator_array",#operator ids txt19 => "$varenv{dbname}", atime => "now()", owner => "198",#update initiated by primary }; #if user_device if ($auth_primary->{c_id} > 0 && $q->param('user_device')){ $update_primary->{txt14} = $q->escapeHTML($session_log) if($session_log); $update_primary->{txt21} = $q->escapeHTML($q->param('user_device')) if($q->param('user_device')); $update_primary->{txt25} = $q->escapeHTML($clientIP) if($clientIP && $clientIP =~ /\d+\.\d+\.\d+\.\d+/); $update_primary->{txt26} = $q->escapeHTML($user_agent) if($user_agent); } my $rows = $dbt->update_record($dbh_primary,$update_primary,$auth_primary); $auth_primary = $dbt->fetch_record($dbh_primary,$authref); } #if user on operator not able to authenticate because of adr authcookie does not exist if(!$auth_operator->{c_id} || $auth_operator->{c_id} == 0 && $cgi_authcookie && length($cgi_authcookie) > 30){ #my $uid = 0; #($uid,my $sec,my $merchant) = split(/_/,$cgi_authcookie); $authref = { table => "contentadr", fetch => "one", template_id => "202", c_id => "=::$auth_primary->{c_id}", #c_id => "=::$uid", #txt05 => "like::" . "%" . $q->escapeHTML($cgi_authcookie) . "%" }; my $auth_operator3 = { c_id => 0 }; $auth_operator3 = $dbt->fetch_record($dbh,$authref);# if($uid); $bw->log("auth_verified on operator anchor 3 by dbname $varenv{dbname}",$auth_operator3->{c_id},""); print FILE "auth_verified on operator anchor 3 by dbname $varenv{dbname} | op3 $auth_operator3->{c_id}\n" if($debug); #if user on operator available by userid c_id, then update authcookie if($auth_operator3->{c_id} > 0){ my $authcookies = $auth_operator3->{txt05} . "|" . $cgi_authcookie; $bw->log("UPDATE adr on operator by dbname $varenv{dbname}",$auth_operator3->{c_id},""); print FILE "UPDATE adr on operator by dbname $varenv{dbname} | op3 $auth_operator3->{c_id}\n" if($debug); my $update = { table => "contentadr", #txt05 => "$authcookies",#authcookies txt05 => "$auth_primary->{txt05}",#authcookies atime => "now()", #mtime => "now()",#only set mtime on real user-data change owner => "198",#update initiated by primary }; my $rows = $dbt->update_record($dbh,$update,$auth_operator3); #else insert authenticated user from primary to operator # }elsif($auth_primary->{txt17} && $auth_primary->{txt17} =~ /$varenv{dbname}/){ #insert my $c_id = 0; if($auth_primary->{c_id} > 0){ $bw->log("INSERT adr from record_primary to operator by dbname $varenv{dbname}",$auth_primary->{c_id},""); print FILE "INSERT adr from record_primary to operator by dbname $varenv{dbname} | pri $auth_primary->{c_id}\n" if($debug); my $insert = { %$auth_primary, table => "contentadr", mtime => 'now()', owner => "198", }; $c_id = $dbt->insert_contentoid($dbh,$insert,"reset_adropkeys"); } }else{ $bw->log("auth_verified on operator anchor 3 FAILS by dbname $varenv{dbname}. user seem not be activated",$auth_operator->{c_id},""); print FILE "auth_verified on operator anchor 3 FAILS by dbname $varenv{dbname}. user seem not be activated | op $auth_operator->{c_id}\n" if($debug); } } $auth_operator = $dbt->fetch_record($dbh,$authref); if($auth_operator->{c_id} > 0){ $record = $auth_operator;#At first try using operator to get Tarif $bw->log("auth_verified on operator anchor 2.2 by dbname $varenv{dbname}",$auth_operator->{c_id},""); print FILE "auth_verified on operator anchor 2.2 by dbname $varenv{dbname} | op $auth_operator->{c_id}\n" if($debug); }else{ $record = $auth_primary; $bw->log("auth_verified on primary anchor 2.3 by dbname $varenv{dbname}",$auth_primary->{c_id},""); print FILE "auth_verified on primary anchor 2.3 by dbname $varenv{dbname} | pri $auth_primary->{c_id}\n" if($debug); } }else{# if($auth_primary->{c_id}) fails $bw->log("auth_verified on primary anchor 4 FAILS by dbname $varenv{dbname}.",$auth_primary->{c_id},""); print FILE "auth_verified on primary anchor 4 FAILS by dbname $varenv{dbname} | pri $auth_primary->{c_id}\n" if($debug); #$auth_operator = $dbt->fetch_record($dbh,$authref); #$record = $auth_operator; #$bw->log("auth_verified on operator anchor 9 by dbname $varenv{dbname}.",$auth_operator->{c_id},""); #print FILE "auth_verified on operator anchor 9 by dbname $varenv{dbname} | op $auth_operator->{c_id}\n" if($debug); } }else{# if($varenv{dbname} eq "sharee_primary") $auth_primary = $dbt->fetch_record($dbh,$authref); $bw->log("auth_verified on operator anchor 4 by dbname $varenv{dbname}",$auth_primary->{c_id},""); print FILE "auth_verified on operator anchor 4 by dbname $varenv{dbname} | pri $auth_primary->{c_id}\n" if($debug); $record = $auth_primary; }#end if($varenv{dbname} ne "sharee_primary") if($varenv{dbname} ne "sharee_primary"){ ($bike_group,$user_group,$tariff_content,$user_tour) = $self->fetch_tariff($varenv{dbname},$record,$q->param('authcookie')); } if($auth_primary->{c_id} > 0 && length($auth_primary->{txt05}) > 30){ my @check_cookies = split(/\|/,$auth_primary->{txt05}); foreach(@check_cookies){ if(length($_) > 30 && $_ =~ /$cgi_authcookie/){ $return->{authcookie} = $cgi_authcookie; $return->{user_id} = $record->{txt08}; $return->{user_group} = $user_group; $return->{user_tour} = $user_tour; $return->{debuglevel} = "$record->{int11}" if($record->{int11}); $return->{Ilockit_admin} = "$record->{int19}" if($record->{int19}); } } } }elsif($userc_id && looks_like_number($userc_id) && length($userc_id) >= 4){ my $authref = { table => "contentadr", fetch => "one", template_id => "202", c_id => "=::$userc_id", }; $record = $dbt->fetch_record($dbh,$authref); ($bike_group,$user_group,$tariff_content,$user_tour) = $self->fetch_tariff($varenv{dbname},$record,$q->param('authcookie')); #maybe there isnt't any authcookie still available on confirm if ($record->{c_id} > 0){ $return->{user_id} = $record->{txt08}; $return->{user_group} = $user_group; $return->{user_tour} = $user_tour; $return->{debuglevel} = "$record->{int11}" if($record->{int11}); $return->{Ilockit_admin} = "$record->{int19}" if($record->{int19}); $return->{response_text} = "Danke, die Anmeldebestätigung war erfolgreich."; } }else{ $bw->log("auth_verified on operator anchor FAILS by dbname $varenv{dbname}, no authcookie, dump \$q",$q,""); print FILE "auth_verified on operator anchor FAILS by dbname $varenv{dbname}, no authcookie\n" if($debug); } $return->{agb_checked} = "0"; $return->{agb_checked} = "1" if($record->{int14});#sharee AGB global 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"); my $hotline_hash = { table => "contentuser", fetch => "one", template_id => 197, c_id => "1", }; my $hotline_data = $dbt->fetch_record($dbh_operator,$hotline_hash); $return->{last_used_operator} = { "operator_name" => "", "operator_hours" => "", "operator_color" => "", "operator_logo" => "", "operator_phone" => "", "operator_email" => "", }; $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_color} = $hotline_data->{txt85} if($hotline_data->{txt85}); $return->{last_used_operator}->{operator_logo} = $hotline_data->{img01} if($hotline_data->{img01}); $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}); } $bw->log("auth_verify done on txt05 authcookies by dbname $varenv{dbname}:",$record->{txt05},""); #Servicetool only users with users.int09=1 #shareetool if($varenv{dbname} ne "sharee_primary" && $return->{merchant_id} && $dbt->{merchant_ids}->{$return->{merchant_id}}->{id} && $dbt->{merchant_ids}->{$return->{merchant_id}}->{id} == 187){ my $users_serviceapp = { u_id => 0 }; $users_serviceapp = $dbt->select_users($dbh,$record->{c_id},"and int09=1"); $bw->log("users_serviceapp: $users_serviceapp->{u_id} && $varenv{dbname} && $return->{merchant_id} && $dbt->{merchant_ids}->{$return->{merchant_id}}->{id}","",""); if(!$users_serviceapp->{u_id} || $users_serviceapp->{u_id} == 0){ $record = { c_id => 0 }; $return = { c_id => 0 }; $bw->log("reset auth_verify because of only Servicetool users access:",$record,""); } print FILE "users_serviceapp: $users_serviceapp->{u_id} | $return->{authcookie}\n" if($debug); } print FILE "final return: $return->{authcookie}\n" if($debug); close(FILE) if($debug); return ($return,$record); }#end auth_verify #authorization sub authorization(){ my $self = shift; my $q = shift; my $merchant_id = shift || $q->param('merchant_id') || ""; my $hw_id = shift || $q->param('hw_id') || ""; my $aowner = shift || 0; $dbh = ""; my %varenv = $cf->envonline(); my $user_id = $q->param('user_id') || $q->param('txt08'); my $user_pw = $q->param('user_pw') || $q->param('txt04'); #print "user_pw:" . $q->param('user_pw') . "|txt04:" . $q->param('txt04') . "|user_pw:" . $q->param('user_pw'); my $pw_length = 8; my $record = { c_id => 0 };#if fails my $return = { authcookie => "" };#if fails #print "$hw_id | $merchant_id | $user_id | $user_pw\n";exit; if($user_id && length($user_id) >= 4 && $user_pw && length($user_pw) >= $pw_length && length($hw_id) >= 10 && length($merchant_id) >= 8){ my $authref = { table => "contentadr", fetch => "one", template_id => "202", txt08 => "ilike::" . $q->escapeHTML($user_id), int05 => "1", }; my $pass_name = $q->escapeHTML($user_pw); $pass_name =~ s/\s//g; my $pwmd5=md5_hex($pass_name); $authref->{txt11} = "$pwmd5"; #Servicetool, only users with users.int09=1 #shareetool if($varenv{dbname} ne "sharee_primary" && $aowner && $aowner eq "187"){ my $users_serviceapp = { u_id => 0 }; $users_serviceapp = $dbt->select_users($dbh,$record->{c_id},"and int09=1"); $record = { c_id => 0 } if(!$users_serviceapp->{u_id}); }else{ #2021-10-13 because of keep DMS authcookie #2021-12-23 user must always be registered on sharee_primary $dbh = $dbt->dbconnect_extern("sharee_primary") if($varenv{dbname} ne "sharee_primary"); $record = $dbt->fetch_record($dbh,$authref); } $return = $self->authcookie_manager($dbh,$q,$record,$merchant_id,$hw_id,$aowner); }else{ $bw->log("authorization fails because of failing condition: if($user_id && length($user_id) >= 4 && length($user_pw) >= $pw_length && length($hw_id) >= 10 && length($merchant_id) >= 8)","",""); } return $return; }#end authorization #manage authcookie sub authcookie_manager { my $self = shift; $dbh = shift; my $q = shift; my $record = shift; my $merchant_id = shift; my $hw_id = shift; my $aowner = shift || 0; my $user_agent = $q->user_agent(); my $clientIP = $q->remote_addr(); my $return = { authcookie => "" };#if fails my %varenv = $cf->envonline(); my $authcookie=md5_hex($record->{txt08}.$q->escapeHTML($hw_id)); $authcookie = $record->{c_id} . "_" . $authcookie . "_" . $q->escapeHTML($merchant_id); #if user_id && user_pw matched if ($record->{c_id} > 0 && length($authcookie) > 20){ my $update = { table => "contentadr", atime => "now()", int15 => "$aowner",#update on access #mtime => "now()", #owner => "198",#update initiated by primary }; $update->{txt21} = $q->escapeHTML($q->param('user_device')) if($q->param('user_device')); $update->{txt25} = $q->escapeHTML($clientIP) if($clientIP && $clientIP =~ /\d+\.\d+\.\d+\.\d+/); $update->{txt26} = $q->escapeHTML($user_agent) if($user_agent); my @registered_cookies; my $registered_cookies; my @check_cookies = split(/\|/,$record->{txt05}); $bw->log("check_cookies","@check_cookies",""); @check_cookies = reverse(@check_cookies); my $i=0; foreach(@check_cookies){ $i++; #secure shortage cookies if(length($_) > 20 && $i < 8){#max 8 clients $bw->log("$i < 8 cookies",$_,""); push @registered_cookies,$_; } } @registered_cookies = reverse(@registered_cookies); foreach(@registered_cookies){ $registered_cookies .= "$_|" if(length($_) > 20);#secure shortage cookies } $registered_cookies =~ s/\|$//; $bw->log("generated authcookie",$authcookie,""); #return still existing authcookie if($registered_cookies && $registered_cookies =~ /$authcookie/){ my $rows = $dbt->update_record($dbh,$update,$record); $return = { authcookie => "$authcookie", new_authcoo => "0", user_id => "$record->{txt08}", }; #return new generated authcookie }else{ my $all_authcookie = $authcookie; $all_authcookie = $registered_cookies . "|" . $authcookie if($registered_cookies); $update->{txt05} = $all_authcookie; my $rows = $dbt->update_record($dbh,$update,$record); #update also operator cookies if($varenv{dbname} eq "sharee_primary" && $record->{txt17}){ my $auth_primary = $record; my %operator_hash = (); if($auth_primary->{txt17} =~ /\w\s\w/){ %operator_hash = map { $_ => 1 } split(/\s+/,$auth_primary->{txt17}); }else{ $operator_hash{$auth_primary->{txt17}} = 1; } foreach my $sharee_operator (keys (%operator_hash)){ my $dbh_operator = $dbt->dbconnect_extern("$sharee_operator"); my $authref = { table => "contentadr", fetch => "one", template_id => "202", c_id => "$auth_primary->{c_id}", }; my $auth_operator = { c_id => 0 }; $auth_operator = $dbt->fetch_record($dbh_operator,$authref); #if user on operator available by userid c_id, then update authcookie if($auth_operator->{c_id}){ $bw->log("update adr from record_primary to operator \"$sharee_operator\" after new new_authcoo",$update,""); my $rows = $dbt->update_record($dbh_operator,$update,$auth_operator); } } } #end update operator cookies if($rows == 1){ $return = { authcookie => "$authcookie", new_authcoo => "1", user_id => "$record->{txt08}", }; } } } $return->{debuglevel} = "$record->{int11}" if($record->{int11}); $return->{Ilockit_admin} = "$record->{int19}" if($record->{int19}); $return->{agb_checked} = "0"; $return->{agb_checked} = "1" if($record->{int14});#sharee AGB global return $return; } 1;