sharee.bike/copri4/main/src/Mod/APIfunc.pm
2022-12-30 19:51:45 +01:00

3081 lines
124 KiB
Perl
Executable file

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}}) {
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')) && $q->param('request') ne "service_done"){
$pref->{c_id} = "=::" . $q->escapeHTML($q->param('service_id'));
}elsif(looks_like_number($service_id) && $q->param('request') ne "service_done"){
$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 = $q->escapeHTML($q->param('bike'));
my $bike_id = $bike;
$bike_id =~ s/S[1-9]X/SX/;
$bike_id = $1 if($bike_id =~ /(\d+)/);
$insert->{barcode} = $bike_id;
$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_id",
};
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 = {};
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 $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",
int10 => "1",
end_time => ">=::(now() - interval '5 min')",
};
my $ctpos = { c_id => 0 };
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'));
$ctpos = $dbt->collect_post($dbh,$pref) if($bike_id);
if($ctpos->{c_id} > 0){
my $update_pos = {
table => "contenttranspos",
mtime => "now()",
int27 => 1,#ok marker for rental end ack
};
#update sig int28 counter
$update_pos->{int28} = 2 if($ctpos->{int28} && $ctpos->{int28} == 3);
#update bike charge on pos and content
if(looks_like_number($q->param('charge_current_bars'))){
my $max_bars = 5;
my $current_percent = $bw->battery_percent($max_bars,$q->param('charge_current_bars'));
$update_pos->{int19} = $current_percent;
#NO, because of service_work should also be deleted if > 50%
#$self->service_automatic($q,$current_percent) if($current_percent <= 50);
#update also bike charge
my $update_bike = {
table => "content",
mtime => "now()",
int19 => "$update_pos->{int19}",
};
my $record_bike = { c_id => 0 };
$record_bike->{c_id} = $ctpos->{cc_id} if($ctpos->{cc_id});
$dbt->update_record($dbh,$update_bike,$record_bike) if($record_bike->{c_id} > 0);
}
$dbt->update_record($dbh,$update_pos,$ctpos);
}
}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'));
#just a assumption
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}",
end_time => ">=::(now() - interval '5 min')",
};
my $post_record = { c_id => 0 };
$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};
#to update sig int28 counter
my $update_pos = {
table => "contenttranspos",
mtime => "now()",
int28 => "1",
};
$dbt->update_record($dbh_operator,$update_pos,$post_record) if($post_record->{c_id});
#user_miniquest_count on operator
#my $adref = {
# table => "contentadr",
# fetch => "one",
# template_id => "202",
# c_id => "$auth->{c_id}",
# };
#my $auth_op = $dbt->fetch_record($dbh_operator,$adref);
my $user_miniquest_count = $auth->{int23} || 0;
if($user_miniquest_count <= 3){
$user_miniquest_count++;
my $update23 = {
table => "contentadr",
int23 => $user_miniquest_count,
atime => "now()",
};
my $rows = $dbt->update_record($dbh,$update23,$auth);
}
}
}
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'));
}
}
}
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("bikestate_update bike to state c_id $c_id | $update->{int04} | $state | auth:$auth->{c_id}",$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 $j=0;
my $article = $article_all->{$cid}->{barcode};
my $tpl_keyseen = "";
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
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::/);
#service integer collect
if($key =~ /int/ && looks_like_number($pos_record->{$id}->{$key})){
$tpl_keyseen .= "$key|";
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 );
$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}";
$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}";
#servive multi todo collect
}elsif($key eq "txt01" && $pos_record->{$id}->{$key} && $pos_record->{$id}->{$key} ne "NaN" && $erledigt){
$j++;
$tpl_keyseen .= "$key|";
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 );
$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;
}elsif($j > 1){
#appending counter on multiple todos
$key_change .= "_" . $j;
}
$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}";
$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
if(!$history && scalar(@tpl_order) > 1){
$bw->log("set service init values by @tpl_order","","");
$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-09-29 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,$bike_node,$user_tour,$tariff_content,$adrtarif_hash) = $self->fetch_tariff($varenv->{dbname},$auth,"");
$main_ids = join(",",@{$bike_node});
$main_ids =~ s/[a-z_]+//ig;
my $ct_bike = {};
my $pref_cc = {
table => "content",
fetch => "one",
main_id => "IN::($main_ids)",
barcode => $bike_id,
template_id => 205,
#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)){
#</sharing_type>
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_node: @{$bike_node} main_ids:$main_ids | bike_group by type_id:@{$bike_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 $q = 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 $state = $q->escapeHTML($q->param('state')) || "";
my $lock_state = $q->escapeHTML($q->param('lock_state')) || "";
my $dbh = "";
my $pos_id="";
my $now_dt = strftime "%Y-%m-%d %H:%M", localtime;
my $response_state = "OK";
my $response_text = "";
#state and lock_state is only defined if requestes incl. occupied
$bw->log("booking_request bike to state $bike | $state | $lock_state, tarif $ct_tariff->{barcode}, auth:$auth->{c_id}",$auth->{c_id},"");
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){
#to get if station only for A-A journay
my $pref_station = {
table => "content",
fetch => "one",
template_id => "225",
int04 => $ct_bike->{int04},
};
my $ct_station = {};
$ct_station = $dbt->fetch_record($dbh,$pref_station) if($ct_bike->{int04});
#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,$ct_station,$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",
pos_id => "$pos_id",
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 $dbh = "";
my $state = $q->escapeHTML($q->param('state')) || "";
my $lock_state = $q->escapeHTML($q->param('lock_state')) || "";
my %varenv = $cf->envonline();
my $rows = 0;
my $user_agent = $q->user_agent();
#my $bike = $q->param('bike');
#my $bike_id = $1 if($q->escapeHTML($q->param('bike')) =~ /(\d+)/);
my $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_lock_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')",
};
my $record_pos = { c_id => 0 };
$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 = { c_id => 0 };
$record_cc = $dbt->fetch_record($dbh,$pref_cc) if($q->param('bike'));
$bw->log("booking_update bike to state $bike | $state | $lock_state, auth:$auth->{c_id}",$auth->{c_id},"");
my $update_cc = {
table => "content",
mtime => "now()",
owner => "$owner",
};
my $gps_data = {
gps => "",
latitude => "",
longitude => "",
gps_age_minutes => 60,
gps_accuracy => 0,
geo_distance => 1000000,
};
#old
if($q->param('gps')){
my $gps_input = $q->param('gps');
$gps_input =~ s/\s//g;
$gps_data->{latitude} = $q->escapeHTML($1) if($gps_input =~ /^(\d+\.\d+),\d+/);
$gps_data->{longitude} = $q->escapeHTML($1) if($gps_input =~ /\d+,(\d+\.\d+)$/);
$gps_data->{gps} = "$gps_data->{latitude},$gps_data->{longitude}" if($gps_data->{latitude} && $gps_data->{longitude});
}
#new
if($q->param('latitude') && $q->param('longitude')){
my $latitude_in = $q->param('latitude');
my $longitude_in = $q->param('longitude');
$gps_data->{latitude} = $1 if($latitude_in =~ /(\d+\.\d+)/);
$gps_data->{longitude} = $1 if($longitude_in =~ /(\d+\.\d+)/);
$gps_data->{gps} = "$gps_data->{latitude},$gps_data->{longitude}" if($gps_data->{latitude} && $gps_data->{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+$/);
#$update_pos->{txt17} = $Ilockit_GUID if($Ilockit_GUID);
$update_cc->{txt17} = $Ilockit_GUID if($Ilockit_GUID);
my $gps_age = 0;
$gps_age = $1 if($q->param('gps_age') =~ /^(\d+)/);#in milisec
$gps_data->{gps_age_minutes} = $gps_age / 1000 / 60 if($gps_age);
$gps_data->{gps_accuracy} = $1 if($q->param('gps_accuracy') =~ /^(\d+)/);#in meters
#2022-10-02 manage lock_state before state
if($lock_state && $lock_state =~ /locking|locked|unlocking|unlocked/ && $record_pos->{cc_id} && $record_pos->{cc_id} > 0){
$booking_values = $self->smartlock($q,$varenv,$auth,$owner,$record_pos,$record_cc,$gps_data,$booking_values);
my $booking_pos = {
table => "contenttranspos",
fetch => "one",
c_id => "$record_pos->{c_id}",
};
$record_pos = $dbt->fetch_tablerecord($dbh,$booking_pos);
my $if_gps = $gps_data->{gps} || "";
$bw->log("smartlock lock_state $bike $lock_state | int10 $record_pos->{int10} | int20 $record_pos->{int20} | if_gps $if_gps",$booking_values,"");
}
#6 = "canceled"|3 = "occupied"|1 = "available"
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",
mtime => "now()",
};
if($user_agent && $user_agent !~ /axios/){#keep device info if sig push
$update_pos->{txt21} = $q->escapeHTML($q->param('user_device')) if($q->param('user_device'));
$update_pos->{txt26} = $q->escapeHTML($user_agent) if($user_agent);
$update_pos->{txt27} = $q->escapeHTML($q->param('app_debug')) if($q->param('app_debug'));
}
#if($state eq canceled && $record_pos.state eq requested && $record_pos.lock_state eq locked)
if($state_key == 6 && $record_pos->{int10} == 2 && $record_pos->{int20} == 1){
$rows = $dbt->delete_content($dbh,"contenttranspos",$record_pos->{c_id});
if($rows > 0){
$update_cc->{int10} = 1 if($record_cc->{int10} == 2);#only if still requested
$booking_values->{response_state} = "OK: canceled bike " . $q->param('bike');
$booking_values->{response_text} = "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{
#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} = "$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_data->{gps_age_minutes};
$update_pos->{int22} = $gps_data->{gps_accuracy};
$update_pos->{owner} = "$owner";
$update_pos->{int10} = 3;
$update_pos->{txt11} = "$sig_book->{rentalId}" if($sig_book->{rentalId});
$update_pos->{txt22} = "$sig_book->{bikeId}" if($sig_book->{bikeId});
$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. ";
$update_cc->{int10} = 3;
}
#fraud_rental sms_message
if($auth->{txt29} && $auth->{txt29} =~ /Betrug/){
$bw->log("$varenv->{basedir}/src/scripts/sms_message.pl $varenv->{syshost} fraud_renatl $auth->{txt07} $record_pos->{c_id}",$record_pos->{c_id},"");
system("$varenv->{basedir}/src/scripts/sms_message.pl $varenv->{syshost} fraud_rental $auth->{txt07} $record_pos->{c_id} &");
}
#rental end only if locked
#if(state eq available && $record_pos.lock_state eq locked and pos-state 2=requested or 3=occupied
}elsif($state_key == 1 && $record_pos->{int20} == 1 && ($record_pos->{int10} == 2 || $record_pos->{int10} == 3)){
#client GPS must have. sigo ist done without client gps
if(($gps_data->{gps} && $gps_data->{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,$record_pos);
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($gps_data->{latitude}) || !looks_like_number($gps_data->{longitude})) && ($record_pos->{int11} != 3)){
$geo_debug .= "ERROR no user GPS: $stations_raw->{$id}->{barcode}|$gps_data->{latitude},$gps_data->{longitude},$latitude_station,$longitude_station --> $gps_data->{geo_distance} Meter\n";
}elsif((looks_like_number($gps_data->{latitude}) && looks_like_number($gps_data->{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()";
$gps_data->{geo_distance} = $lb->geo_fencing($gps_data->{latitude},$gps_data->{longitude},$latitude_station,$longitude_station);
#sigo development workaround without geofence
if(($gps_data->{geo_distance} <= $stations_raw->{$id}->{int06}) || ($record_pos->{int11} == 3)){
$geo_distance_next = $gps_data->{geo_distance};
#end-Station
$update_pos->{int04} = $stations_raw->{$id}->{int04};
$update_cc->{int04} = $stations_raw->{$id}->{int04};
$update_pos->{int10} = 1;
$update_pos->{txt11} = "$sig_book->{rentalId}" if($sig_book->{rentalId});
$update_cc->{txt06} = "$gps_data->{gps}";#end content coordinates
$update_pos->{txt06} = "$gps_data->{gps}";#end pos coordinates
$update_pos->{int21} = $gps_data->{gps_age_minutes};
$update_pos->{int22} = $gps_data->{gps_accuracy};
$update_pos->{int23} = $gps_data->{geo_distance};
$update_pos->{int26} = "$sig_book->{distance}" if($sig_book->{distance});
$update_pos->{int28} = "$sig_book->{station_lock_state}" if($sig_book->{station_lock_state});
#end-Station prefix
$update_pos->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}";
$update_cc->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}";
#return after booking_update
my ($pricing,$counting) = $pri->counting_rental(\%varenv,$record_pos,"");
#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){
$update_cc->{int10} = 1;
$booking_values->{response_state} = "OK: available bike " . $q->param('bike');
$booking_values->{response_text} = "Danke! Die Miete Fahrrad Nr. " . $q->param('bike') . " wurde beendet.";
}
$geo_debug .= "Matching station: $stations_raw->{$id}->{barcode}|$gps_data->{latitude},$gps_data->{longitude},$latitude_station,$longitude_station --> $gps_data->{geo_distance} Meter\n";
last;
}else{
if($gps_data->{geo_distance} <= $geo_distance_next){
$geo_distance_next = $gps_data->{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_data->{gps}";#end content coordinates
$update_pos->{txt06} = "$gps_data->{gps}";#end pos coordinates
$update_pos->{int21} = $gps_data->{gps_age_minutes};
$update_pos->{int22} = $gps_data->{gps_accuracy};
$update_pos->{int23} = $gps_data->{geo_distance};
#end-Station prefix
$update_pos->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}";
$update_cc->{txt13} = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}";
#return after booking_update
my ($pricing,$counting) = $pri->counting_rental(\%varenv,$record_pos,"");
#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}|$gps_data->{latitude},$gps_data->{longitude},$latitude_station,$longitude_station --> $geo_distance_next Meter ($geo_distance_next <= $gps_data->{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}|$gps_data->{latitude},$gps_data->{longitude},$latitude_station,$longitude_station --> $gps_data->{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_data->{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_data->{gps_age_minutes} minutes too old, state change forbidden.";
$booking_values->{response_text} = "Fehler! GPS Daten sind mit $gps_data->{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" && $record_pos.state eq occupied || $record_pos.lock_state ne locked
}elsif($state_key == 6 && ($record_pos->{int10} == 3 || $record_pos->{int20} != 1)){
$booking_values->{response_state} = "Failure 2012: occupied bike " . $q->param('bike') . " cannot be state $state and $lock_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 $state and $lock_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);
}
#end Ilockit || sigo
}else{
$bw->log("smartlock type not defined, int11:",$record_pos->{int11},"");
}
#update bike content
$bw->log("check ct_state on update_cc 2.",$update_cc,"");
$dbt->update_record($dbh,$update_cc,$record_cc);
}#end if $state =~ /canceled|occupied|available/
#fetch final booking state after request
if($record_pos->{c_id} && $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} = "$dbt->{copri_conf}->{lock_state}->{$booking->{int20}}";
#user_miniquest_count on operator
my $dbh_primary = $dbt->dbconnect_extern($dbt->{primary}->{sharee_primary}->{database}->{dbname});
my $adref = {
table => "contentadr",
fetch => "one",
template_id => "202",
c_id => "$auth->{c_id}",
};
my $auth_prim = $dbt->fetch_record($dbh_primary,$adref);
if($booking->{int10} == 1 && $dbt->{operator}->{$varenv{dbname}}->{project} eq "Bayern" && $auth_prim->{int23} < 4){
$bw->log("user_miniquery user ID $auth_prim->{c_id} exist count:",$auth_prim->{int23},"");
$booking_values->{user_miniquery} = $dbt->evaluationsfragen($dbh);
#user_miniquest_count
my $user_miniquest_count = $auth_prim->{int23} || 0;
if($user_miniquest_count <= 3){
$user_miniquest_count++;
my $update23 = {
table => "contentadr",
int23 => $user_miniquest_count,
atime => "now()",
};
$rows = $dbt->update_record($dbh,$update23,$auth_prim);
}
}#end mini_quest
#fetch tracking distance on Ilockit cloud by summary trip if(tracking && deviceId && available)
if($booking->{int25} == 1 && $booking->{int10} == 1){
$bw->log("get co2saving",$booking->{c_id},"");
#if system=ilockit && clouid
if($record_pos->{int11} == 2 && $booking->{int13}){
sleep 2;#hopefully get distance in 2 sec.
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 = "";
if($booking->{int26}){
$co2saving = "Einsparung: ";
my $co2diff = $pri->co2calc($booking);
#my $sprit_price = $pri->sprit2calc($booking);
$co2saving .= "$co2diff kg CO2, ";
#$co2saving .= "$sprit_price EUR " if($sprit_price !~ /-/);
$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 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
$xml .= "<sharee_LastenVelo>\n";
$xml .= "<todo>available</todo>\n";
$xml .= "<bikeID>$booking_values->{bike}</bikeID>\n";
$xml .= "<userID>$auth->{int01}</userID>\n";
$xml .= "<emailID>$auth->{txt08}</emailID>\n";
$xml .= "</sharee_LastenVelo>\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
#
#smartlock state on request update
sub smartlock {
my $self = shift;
my $q = shift;
my $varenv = shift;
my $auth = shift;
my $owner = shift || 0;
my $record_pos = shift || {};
my $record_cc = shift || {};
my $gps_data = shift || {};
my $booking_values = shift || {};
my $user_agent = $q->user_agent();
my $dbh = "";
#content
my $update_cc = {
table => "content",
mtime => "now()",
owner => "$owner",
};
$update_cc->{txt28} = $q->escapeHTML($q->param('firmware')) if($q->param('firmware'));
#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,
};
if($user_agent && $user_agent !~ /axios/){#keep device info if sig push
$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);
$update_pos->{txt27} = $q->escapeHTML($q->param('app_debug')) if($q->param('app_debug'));
$update_pos->{txt28} = $q->escapeHTML($q->param('firmware')) if($q->param('firmware'));
}
my $lock_value = 0;
if($q->param('lock_state') eq "locked"){
$lock_value = 1;
$update_cc->{int20} = "$lock_value";
$update_pos->{int20} = "$lock_value";
$update_pos->{end_time} = "now()";
$update_cc->{txt06} = $gps_data->{gps};#end content coordinates
$update_pos->{txt06} = $gps_data->{gps};#end pos coordinates
$update_pos->{int21} = $gps_data->{gps_age_minutes};
$update_pos->{int22} = $gps_data->{gps_accuracy};
$update_pos->{int23} = "null";# only computed on rental-end
$booking_values->{response_state} = "OK: bike " . $q->param('bike') . " locked confirmed. ";
$booking_values->{response_text} = "Abschließen von Fahrrad Nr. " . $q->param('bike') . " bestätigt. ";
}elsif($q->param('lock_state') eq "unlocked"){
$lock_value = 2;
$update_cc->{int20} = "$lock_value";
$update_pos->{int20} = "$lock_value";
$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($q->param('lock_state') eq "locking"){
$lock_value = 3;
$update_cc->{int20} = "$lock_value";
$update_pos->{int20} = "$lock_value";
$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($q->param('lock_state') eq "unlocking"){
$lock_value = 4;
$update_cc->{int20} = "$lock_value";
$update_pos->{int20} = "$lock_value";
$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);
return $booking_values;
}#end smartlock
#
#dedicated service insert automatic
sub service_automatic {
my $self = shift;
my $q = shift || "";
my $current_percent = shift || 0;
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 $charge = "";
if(looks_like_number($q->param('voltage'))){
$charge = "Achtung, Schloss-Akku Ladung " . $q->param('voltage') . "%";
}
if(looks_like_number($q->param('charge_current_bars'))){
$charge = "Achtung, Fahr-Akku Ladung " . $current_percent . "%";
}
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=>"$charge");
my $article = looks_like_number($bike_id) || looks_like_number($station_id);
#insert only new dataset if mtime > 10 days
(my $xresponse->{$article}, my $pos_record, my $node_template, my $crecord) = $self->service_select($q,$authraw,"","10");
my $service_id = "";
foreach my $id (sort { $pos_record->{$a}->{barcode} <=> $pos_record->{$b}->{barcode} } keys (%$pos_record)){
$service_id = $pos_record->{$id}->{c_id} if($pos_record->{$id}->{c_id} > 1);
}
if(!$service_id){
($response->{service_id}) = $self->service_insert($q,$authraw,$node_template,$crecord);
$bw->log("service_automatic insert ($response->{service_id}) ",$response,"");
my $rows = $self->service_update($q,$authraw,$node_template,$response->{service_id});
}elsif($service_id){
my $rows = $self->service_update($q,$authraw,$node_template,$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 $dbt->{primary}->{sharee_primary}->{database}->{dbname}){
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
#last used rental to feedback
sub rental_to_feedback{
my $self = shift;
my $varenv = shift;
my $auth = shift;
my $dbh = "";
my $pref = {
table => "contenttrans",
table_pos => "contenttranspos",
fetch => "one",
template_id => "218",
ca_id => "$auth->{c_id}",
"ct.close_time" => "is::null",
int10 => "1",
int11 => "3",#sig system
int28 => "3",#set count on sig rental_end
end_time => ">=::(now() - interval '5 min')",
};
my $ctpos = { c_id => 0 };
$ctpos = $dbt->collect_post($dbh,$pref);
my $show_dialog = {};
if($dbt->{operator}->{$varenv->{dbname}}->{project} eq "Bayern"){
my $dbh_primary = $dbt->dbconnect_extern($dbt->{primary}->{sharee_primary}->{database}->{dbname});
my $adref = {
table => "contentadr",
fetch => "one",
template_id => "202",
c_id => "$auth->{c_id}",
};
my $auth_prim = $dbt->fetch_record($dbh_primary,$adref);
if(!$auth_prim->{int23} || $auth_prim->{int23} < 4){
$bw->log("user_miniquery via user ID $auth_prim->{c_id} exist count:",$auth_prim->{int23},"");
$show_dialog->{user_miniquery} = $dbt->evaluationsfragen($dbh);
}
$show_dialog->{co2saving} = "";
if($ctpos->{int26}){
my $co2saving = "Einsparung: ";
my $co2diff = $pri->co2calc($ctpos);
#my $sprit_price = $pri->sprit2calc($ctpos);
$co2saving .= "$co2diff kg CO2, ";
#$co2saving .= "$sprit_price EUR " if($sprit_price !~ /-/);
$ctpos->{int26} =~ s/\./,/;
$co2saving .= "bei einer Strecke von $ctpos->{int26} KM";
$show_dialog->{co2saving} = $co2saving;
}
}
return ($ctpos,$show_dialog);
}
#user bikes occupied
sub user_bikes_occupied(){
my $self = shift;
my $q = shift;
my $auth = shift;
my $show_dialog = 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",
};
##selects also int28 > 0 bikes to view once miniquery
#it will only defined on booking_request, because there must be available
#$pref->{show_dialog} = "1" if($show_dialog);
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)){
#new sharee_pricing
(my $return_counting->{$id}, my $counting) = $pri->counting_rental(\%varenv,$record->{$id},"");
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");
}
}
$bw->log("user_bikes_occupied rentals bike $return->{$id}->{bike} | station $return->{$id}->{station} | state $return->{$id}->{state}, auth:$auth->{c_id}",$return->{$id}->{c_id},"");
}
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 $lang = "de";
my $station = $q->escapeHTML($q->param('station')) || "";
my $station_id = "";
$station_id = $1 if($station =~ /(\d+)$/);
#to get A-A key for text
my $pref_st = {
table => "content",
fetch => "all",
keyfield => "int04",
template_id => "225",
int10 => "1",
};
my $record_st = {};
$pref_st->{int04} = "$station_id" if($station_id);
$record_st = $dbt->fetch_record($dbh,$pref_st);
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 = {};
my $adrtarif_hash = {};
$authed = 1 if(ref($auth) eq "HASH" && $auth->{c_id} > 0);
(my $bike_group,my $bike_node,my $user_tour,$tariff_content,$adrtarif_hash) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie'));
#print Dumper($bike_group);
#print Dumper($bike_node);
my $main_ids = join(",",@{$bike_node});
$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 = {};
$record = $dbt->fetch_record($dbh,$pref) if(ref($bike_node) eq "ARRAY" && @{$bike_node}[0]);
my $op_return = {};
my $td_template = $dbt->rental_description_template();
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}";
my $description = $q->unescapeHTML($record->{$id}->{txt01}) || "";
$return->{$id}->{description} = "$description";
#$return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $description));
$return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}";
$return->{$id}->{lock_state} = "$dbt->{copri_conf}->{lock_state}->{$record->{$id}->{int20}}";
#defaults
$return->{$id}->{bike_group} = [];
$return->{$id}->{bike_type}->{category} = "city";
$return->{$id}->{bike_type}->{wheels} = "2";
#for station_type_id mapping
if($record->{$id}->{type_id}){
$return->{$id}->{bike_group} = ["$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{type_id}"];
if($record->{$id}->{type_id} == 300101){
$return->{$id}->{bike_type}->{category} = "cargo";
$return->{$id}->{bike_type}->{wheels} = "2";
$return->{$id}->{bike_type}->{wheels} = "3" if($record->{$id}->{txt01} =~ /drei|trike/i);
if($record->{$id}->{energy_id} || $record->{$id}->{txt01} =~ /E-/i){
$return->{$id}->{bike_type}->{engine}->{manufacturer} = "dummy";
my $max_bars = 5;
my $current_bars = 0;
my $charge_view_hidden = 0;#1=hide charge view
#$charge_view_hidden = 0 if($dbt->{operator}->{$varenv->{dbname}}->{oprefix} =~ /BVB|FR|KN/);
my $backend_accessible = 1;
$backend_accessible = 0 if($record->{$id}->{int11} eq "2");#for asking user
#$backend_accessible = 0 if($dbt->{operator}->{$varenv->{dbname}}->{oprefix} =~ /BVB|FR|KN/);#for asking user
$return->{$id}->{bike_type}->{battery}->{charge_max_bars} = "$max_bars";
$return->{$id}->{bike_type}->{battery}->{charge_current_bars} = "$current_bars";
$return->{$id}->{bike_type}->{battery}->{charge_current_percent} = "0";
$return->{$id}->{bike_type}->{battery}->{hidden} = "$charge_view_hidden";
$return->{$id}->{bike_type}->{battery}->{backend_accessible} = "$backend_accessible";
if($record->{$id}->{int19}){
$current_bars = $bw->battery_bars($max_bars,$record->{$id}->{int19});
$return->{$id}->{bike_type}->{battery}->{charge_current_bars} = "$current_bars";
$return->{$id}->{bike_type}->{battery}->{charge_current_percent} = "$record->{$id}->{int19}";
}
}
}
}
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";
}
#2022-12-29 smartlock_type
$return->{$id}->{smartlock_type}->{engine}->{manufacturer} = "$dbt->{copri_conf}->{lock_system}->{$record->{$id}->{int11}}";
$return->{$id}->{smartlock_type}->{battery}->{charge_current_percent} = "$record->{$id}->{int14}";
if(ref($tariff_content) eq "HASH"){
foreach my $tid (sort { $tariff_content->{$a}->{barcode} <=> $tariff_content->{$b}->{barcode} } keys (%$tariff_content)){
foreach my $atid (keys (%$adrtarif_hash)){
#print "if($record->{$id}->{main_id} == $tariff_content->{$tid}->{int12} && $atid == $tariff_content->{$tid}->{barcode}){\n";
if($record->{$id}->{main_id} == $tariff_content->{$tid}->{int12} && $atid == $tariff_content->{$tid}->{barcode}){
#$bw->log("bikes_available for user c_id: $auth->{c_id} if($record->{$id}->{main_id} == $tariff_content->{$tid}->{int12} && $atid == $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});
#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}->{reserve_timerange} = "15";
$return->{$id}->{rental_description}->{reserve_timerange} = "30" if($record->{$id}->{int11} == 3);#sig timeout time
$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} = ["AAFahrten","Dieses E-Lastenrad darf nur an der Station zurück gegeben werden an der es ausgeliehen wurde!"] if($record_st->{$record->{$id}->{int04}}->{int42});
#$return->{$id}->{rental_description}->{rental_info}->{3} = ["Lowcharge","Die Akkukapazität war zuletzt niedrig. Bitte überprüfen sie vor der Fahrt die Ladung am Fahrraddisplay. Die Miete kann innerhalb 5 Minuten kostenlos abgebrochen werden."] if($record->{$id}->{energy_id} && (!$record->{$id}->{int19} || $record->{$id}->{int19} < 20));
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/\./,/ if($lang eq "de");
$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/\./,/ if($lang eq "de");
$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/\./,/ if($lang eq "de");
$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"];
$return->{$id}->{rental_description}->{tarif_elements}->{$td} = ["$td_template->{$td}->{time02}","$time_unit"];
}
}#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
};
my ($bike_group,$bike_node,$user_tour,$tariff_content,$adrtarif_hash) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie'));
my $main_ids = join(",",@{$bike_node});
$main_ids =~ s/[a-z_]+//ig;
$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));
if(looks_like_number($bike_id)){
$pref->{ barcode} = "=::$bike_id";
$pref->{int10} = "!=::3";#2022-12-02 do not select occupied bikes in servicetool by direct bike-select
}
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_node) eq "ARRAY" && @{$bike_node}[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}";
my $description = $q->unescapeHTML($record->{$id}->{txt01}) || "";
$return->{$id}->{description} = "$description";
#$return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $description));
$return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}";
$return->{$id}->{service_state} = "0";
$return->{$id}->{lock_state} = "$dbt->{copri_conf}->{lock_state}->{$record->{$id}->{int20}}";
#defaults
$return->{$id}->{bike_group} = [];
$return->{$id}->{bike_type}->{category} = "city";
$return->{$id}->{bike_type}->{wheels} = "2";
#for station_type_id mapping
if($record->{$id}->{type_id}){
$return->{$id}->{bike_group} = ["$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{type_id}"];
if($record->{$id}->{type_id} == 300101){
$return->{$id}->{bike_type}->{category} = "cargo";
$return->{$id}->{bike_type}->{wheels} = "2";
$return->{$id}->{bike_type}->{wheels} = "3" if($record->{$id}->{txt01} =~ /drei|trike/i);
if($record->{$id}->{energy_id} || $record->{$id}->{txt01} =~ /E-/i){
$return->{$id}->{bike_type}->{engine}->{manufacturer} = "dummy";
my $max_bars = 5;
my $current_bars = 0;
my $charge_view_hidden = 0;#1=hide charge view
#$charge_view_hidden = 0 if($dbt->{operator}->{$varenv->{dbname}}->{oprefix} =~ /BVB|FR|KN/);
my $backend_accessible = 1;#1=battery charge from backend, 0=asking user
$backend_accessible = 0 if($record->{$id}->{int11} eq "2");#for asking user
#$backend_accessible = 0 if($dbt->{operator}->{$varenv->{dbname}}->{oprefix} =~ /BVB|FR|KN/);#for asking user
$return->{$id}->{bike_type}->{battery}->{charge_max_bars} = "$max_bars";
$return->{$id}->{bike_type}->{battery}->{charge_current_bars} = "$current_bars";
$return->{$id}->{bike_type}->{battery}->{charge_current_percent} = "0";
$return->{$id}->{bike_type}->{battery}->{hidden} = "$charge_view_hidden";
$return->{$id}->{bike_type}->{battery}->{backend_accessible} = "$backend_accessible";
if($record->{$id}->{int19}){
$current_bars = $bw->battery_bars($max_bars,$record->{$id}->{int19});
$return->{$id}->{bike_type}->{battery}->{charge_current_bars} = "$current_bars";
$return->{$id}->{bike_type}->{battery}->{charge_current_percent} = "$record->{$id}->{int19}";
}
}
}
}
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";
}
#2022-12-29 smartlock_type
$return->{$id}->{smartlock_type}->{engine}->{manufacturer} = "$dbt->{copri_conf}->{lock_system}->{$record->{$id}->{int11}}";
$return->{$id}->{smartlock_type}->{battery}->{charge_current_percent} = "$record->{$id}->{int14}";
$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 $record_pos = shift || {};
my $authed = 0;
$authed = 1 if(ref($auth) eq "HASH" && $auth->{c_id});
my ($bike_group,$bike_node,$user_tour,$tariff_content,$adrtarif_hash) = $self->fetch_tariff($varenv->{dbname},$auth,$q->param('authcookie'));
#station_group and bike_group alias bike nodes.type_id
my $station_group = "";
$station_group = $record_pos->{int29} if(ref($record_pos) eq "HASH" && $record_pos->{int29});
#station_bike_node and bike_node alias bike nodes.main_id
my $station_bike_node = "";
$station_bike_node = $record_pos->{int12} if(ref($record_pos) eq "HASH" && $record_pos->{int12});
#take start station from pos
my $aa_station = "";
$aa_station = $record_pos->{int06} if(ref($record_pos) eq "HASH" && $record_pos->{int06} && $record_pos->{int42});
my $return = {};
my $pref = {
table => "content",
fetch => "all",
keyfield => "int04",
template_id => "225",
int10 => "1",#1 = "available"
};
#group_id must have 6 numbers like 300103
my $pref_sql = "";
#select by bike.type_id bike-group on booking update, to get available stations on bike return by filter logic
if(ref($record_pos) eq "HASH" && $record_pos->{int29}){
$pref_sql .= " and (";
foreach my $type_id (@{$bike_group}){
#on rental end select only stations which are defined
#A-A rental
if($station_group && $type_id =~ /(\d+)/ && $aa_station){
my $group_id = $1;
if($group_id == $station_group){
$pref_sql .= " ct.int04 = $aa_station OR";
}
#A-B rental
}elsif($station_group && $type_id =~ /(\d+)/){
my $group_id = $1;
if($group_id == $station_group){
$pref_sql .= " ct.txt25 like '%$group_id%' OR";
}
#without a rental
}elsif(!$station_group && $type_id =~ /(\d+)/){
my $group_id = $1;
$pref_sql .= " ct.txt25 like '%$group_id%' OR";
}
}
$pref_sql =~ s/OR$//;
$pref_sql .= ")";
}
#select by bike.main_id Flot only if no booking update, to keep private/hidden Tarif logic
else{
$pref_sql .= " and (";
foreach my $main_id (@{$bike_node}){
#on rental end select only stations which are defined
#A-A rental
if($station_bike_node && $main_id =~ /(\d+)/ && $aa_station){
my $node_id = $1;
if($node_id == $station_bike_node){
$pref_sql .= " ct.int04 = $aa_station OR";
}
#A-B rental
}elsif($station_bike_node && $main_id =~ /(\d+)/){
my $node_id = $1;
if($node_id == $station_bike_node){
$pref_sql .= " ct.txt24 like '%$node_id%' OR";
}
#without a rental
}elsif($main_id =~ /(\d+)/){
my $node_id = $1;
$pref_sql .= " ct.txt24 like '%$node_id%' OR";
}
}
$pref_sql =~ s/OR$//;
$pref_sql .= ")";
}
$pref_sql = "" if($pref_sql !~ /\d/);
$bw->log("stations_available --> station_bike_node:$station_bike_node|aa_station:$aa_station|bike_node:@{$bike_node}|bike_group:@{$bike_group}|pref_sql:\n",$pref_sql,"");
my $record = {};
$record = $dbt->fetch_record($dbh,$pref,$pref_sql) if(ref($bike_node) eq "ARRAY" && @{$bike_node}[0]);
my $hotline_hash = {
table => "contentuser",
fetch => "one",
template_id => 197,
c_id => "1",
};
my $hotline_data = $dbt->fetch_record($dbh,$hotline_hash);
my $op_return = {};
foreach my $id (sort { $record->{$a}->{barcode} <=> $record->{$b}->{barcode} } keys (%$record)){
$return->{$id}->{authed} = "$authed";
$return->{$id}->{capacity} = "$record->{$id}->{int05}" || "1";
$return->{$id}->{station} = "$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$record->{$id}->{int04}";
$return->{$id}->{uri_operator} = "$varenv->{wwwhost}";
$record->{$id}->{txt06} =~ s/\s//g;
($return->{$id}->{gps}->{latitude},$return->{$id}->{gps}->{longitude}) = split(/,/,$record->{$id}->{txt06});
my $description = $q->unescapeHTML($record->{$id}->{txt01}) || "";
$return->{$id}->{description} = "$description";
#$return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $description));
$return->{$id}->{state} = "$dbt->{copri_conf}->{bike_state}->{$record->{$id}->{int10}}";
$return->{$id}->{gps_radius} = "$record->{$id}->{int06}";
$return->{$id}->{station_group} = "";
if($record->{$id}->{txt25}){
$record->{$id}->{txt25} =~ s/(\d+)/$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$1/g;
my @station_group = split(/\s/,$record->{$id}->{txt25});
$return->{$id}->{station_group} = [@station_group];
}
$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,$bike_node,$user_tour,$tariff_content,$adrtarif_hash) = $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_node}){
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_node) eq "ARRAY" && @{$bike_node}[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($record->{$id}->{description}){
my $description = $q->unescapeHTML($record->{$id}->{txt01}) || "";
$return->{$id}->{description} = "$description";
#$return->{$id}->{description} = Encode::encode('utf-8', Encode::decode('iso-8859-1', $description));
}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} = "";
$return->{$id}->{gps_radius} = "$record->{$id}->{int06}";
if($record->{$id}->{txt25}){
$record->{$id}->{txt25} =~ s/(\d+)/$dbt->{operator}->{$varenv->{dbname}}->{oprefix}$1/g;
my @station_group = split(/\s/,$record->{$id}->{txt25});
$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 Tarif to get users bike access ----------------------
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 = { c_id => 0 };
#int18
#<sharing_type>
# 2 = "public"
# 3 = "private"
# 4 = "hidden-lv"
# 5 = "public-bonus"
#</sharing_type>
my $tariff = {
table => "content",
fetch => "all",
keyfield => "barcode",
template_id => "210",#Tariff tpl_id
};
my ($nodes,$rows) = $dbt->collect_node($dbh,$dbt->{shareedms_conf}->{waren});
#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,"");
}
#select operators address to get users tarifnr array in txt30
elsif(ref($adr) eq "HASH" && $adr->{c_id}){
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 user_tour
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/);
}
}#end user_tour
$tariff->{int18} = 4 if($dbname eq "sharee_lv");
$tariff_content = $dbt->fetch_record($dbh,$tariff);
$bw->log("2. Tariff type $tariff->{int18} select on",$dbname,"");
}
#end operators address
else{
$bw->log("3. NO tariff_content on",$dbname,"");
}
my $oprefix = "";
$oprefix = "$dbt->{operator}->{$dbname}->{oprefix}" if($dbt->{operator}->{$dbname}->{oprefix});
#2022-07-16 refactored
#collect setted user tarifs and available public tarifs
my %adrtarif_hash = ();
if($auth_operator->{c_id}){
if($auth_operator->{txt30} && $auth_operator->{txt30} =~ /\d\s\d/){
%adrtarif_hash = map { $_ => 1 } split(/\s+/,$auth_operator->{txt30});
}else{
$adrtarif_hash{$auth_operator->{txt30}} = 1;
}
}
if(ref($tariff_content) eq "HASH"){
foreach my $tid (keys (%$tariff_content)){
$adrtarif_hash{$tariff_content->{$tid}->{barcode}} = 1 if($tariff_content->{$tid}->{int18} eq 2);
}
}
#collect tarif values for user rentable bikes
my %tarifnr = ();
my %bike_node = ();
my %bike_group = ();
if(ref($tariff_content) eq "HASH"){
foreach my $tid (sort { $tariff_content->{$a}->{barcode} <=> $tariff_content->{$b}->{barcode} } keys (%$tariff_content)){
foreach my $atid (keys (%adrtarif_hash)){
if($tariff_content->{$tid}->{int12} && $tariff_content->{$tid}->{barcode} && $atid == $tariff_content->{$tid}->{barcode}){
$bw->log("Tarif FOUND with merchant $merchant_id for authorized user-id $auth_operator->{c_id} if($tariff_content->{$tid}->{int12}) (s-type:$tariff_content->{$tid}->{int18})",$tariff_content->{$tid}->{barcode},"");
$tarifnr{$tariff_content->{$tid}->{barcode}} = 1;
$bike_node{$oprefix . $tariff_content->{$tid}->{int12}} = 1;#sharee bike_node.main_id
my $type_id = $nodes->{$tariff_content->{$tid}->{int12}}->{type_id} || "";
$bike_group{$oprefix . $type_id} = 1 if($type_id);#sharee bike_node.type_id
}
}
}
}
my @tarifnr = ();
my @bike_node = ();
my @bike_group = ();
@tarifnr = keys %tarifnr;
@bike_node = keys %bike_node;
@bike_group = keys %bike_group;
$bw->log("FETCHED_Tarif by dbname:$dbname with merchant $merchant_id | bike_node:@bike_node | bike_group:@bike_group | user_tour:@user_tour | tarifnr: @tarifnr",\@tarifnr,"");
return (\@bike_group,\@bike_node,\@user_tour,$tariff_content,\%adrtarif_hash);
}
#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);
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 $dbt->{primary}->{sharee_primary}->{database}->{dbname}){
my $dbh_prim = $dbt->dbconnect_extern($dbt->{primary}->{sharee_primary}->{database}->{dbname});
$rows = $dbt->update_record($dbh_prim,$update,$record);
}
if($rows == 1){
$return = { authcookie => "1",
user_id => "$record->{txt08}",
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 $simple_op = 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 $bike_group = "";
my $bike_node = "";
my $user_tour = "";
my $tariff_content = "";
my $adrtarif_hash = "";
$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=0;
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);
$record = $auth_operator;
#$bw->log("auth_verified on operator $varenv{dbname} anchor 1",$auth_operator->{c_id},"");
#just part of operator-routing (sharee account management)
if(!$simple_op && $varenv{dbname} ne $dbt->{primary}->{sharee_primary}->{database}->{dbname}){
#primary select
my $dbh_primary = $dbt->dbconnect_extern($dbt->{primary}->{sharee_primary}->{database}->{dbname});
$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);
$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} && $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} && $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);
}
}elsif($varenv{dbname} eq $dbt->{primary}->{sharee_primary}->{database}->{dbname}){
$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 $dbt->{primary}->{sharee_primary}->{database}->{dbname})
if($varenv{dbname} ne $dbt->{primary}->{sharee_primary}->{database}->{dbname}){
($bike_group,$bike_node,$user_tour,$tariff_content,$adrtarif_hash) = $self->fetch_tariff($varenv{dbname},$record,$q->param('authcookie'));
}
if($record->{c_id} > 0 && length($record->{txt05}) > 30){
my @check_cookies = split(/\|/,$record->{txt05});
foreach(@check_cookies){
if(length($_) > 30 && $_ =~ /$cgi_authcookie/){
$return->{authcookie} = $cgi_authcookie;
$return->{user_id} = $record->{txt08};
$return->{user_group} = $bike_group;#yes, but deprecated
$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,$bike_node,$user_tour,$tariff_content,$adrtarif_hash) = $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} = $bike_group;#yes, but deprecated
$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 $dbt->{primary}->{sharee_primary}->{database}->{dbname} && $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 $dbt->{primary}->{sharee_primary}->{database}->{dbname} && $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($dbt->{primary}->{sharee_primary}->{database}->{dbname}) if($varenv{dbname} ne $dbt->{primary}->{sharee_primary}->{database}->{dbname});
$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);
$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 $dbt->{primary}->{sharee_primary}->{database}->{dbname} && $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;