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