#!/usr/bin/perl # ## SPDX-License-Identifier: AGPL-3.0-or-later # Copyright (c) Rainer Gümpelein, TeilRad GmbH # #csv/Statistik-average_bike_* #csv/Statistik-occubike_station_* #csv/Statistik-average_user_* # #Example citybike #./src/scripts/statistik_occubike_stationCSV.pl shareedms-operator '2022-01-01' '2022-02-01' '300103' # #Example cargobike #Without date defaults to duration of last 1 month up to now #./src/scripts/statistik_occubike_stationCSV.pl shareedms-operator '' '' '300101' # # use vars qw($syshost); BEGIN { $syshost = $ARGV[0] || exit 1; } use lib "/var/www/copri-bike/$syshost/src"; use strict; use warnings; use feature qw(say); use POSIX; use CGI ':standard'; use Lib::Config; use Scalar::Util qw(looks_like_number); use DateTime; use DateTime::Format::Pg; use Text::CSV_XS; use Mod::DBtank; use Mod::Pricing; use Data::Dumper; my $q = new CGI; my $cf = new Config; my %varenv = $cf->envonline(); my $dbt = new DBtank; my $pri = new Pricing; my $dbh = $dbt->dbconnect(); my $start_itime = ""; my $end_itime = ""; my $filename = ""; #If NO date on command then now my $dt1 = DateTime->now(time_zone => 'Europe/Berlin'); if($ARGV[2] && $ARGV[2] =~ /(\d{4})-(\d{2})-(\d{2})/){ $end_itime = DateTime->new( year => $1, month => $2, day => $3, time_zone => 'Europe/Berlin', ); }else{ $end_itime = $dt1; } if($ARGV[1] && $ARGV[1] =~ /(\d{4})-(\d{2})-(\d{2})/){ $start_itime = DateTime->new( year => $1, month => $2, day => $3, time_zone => 'Europe/Berlin', ); }else{ $start_itime = $end_itime->clone->add(months => -1, end_of_month => 'preserve'); } #2022-08-03 changed $bikesys int12 select to $bike_type_id int29 my $bike_type_id = $ARGV[3] || ""; my $flotte = ""; if($bike_type_id == 300101){ $flotte = "Lastenrad"; }elsif($bike_type_id == 300103){ $flotte = "Stadtrad"; }else{ print "Failure, bike_type_id must be nodes.type_id number of Flot\n\n"; exit 1; } my $month = $start_itime->month; $month = sprintf('%.2d',$month); my $year = $start_itime->year; my $sendref = { mail_from => "", mail_to => "ragu\@gnu-systems.de", subject => "$syshost $bike_type_id statistik_occubike_stationCSV $year-$month", message => "", }; $sendref->{message} .= "\nCSV Generation and debugging\n$syshost $bike_type_id $flotte Statistik occupied bike on station $start_itime - $end_itime\n"; $sendref->{message} .= "CSV Attachemnt will be sent by loop_statistik_monthly.pl after CSV generation to get it\n\n"; my $month_days = DateTime->last_day_of_month( year => $year, month => $month, ); my $days = $1 if($month_days =~ /\d{4}-\d{2}-(\d{2})/); $sendref->{message} .= "occubike on station\n"; #fetch stations my $pref = { table => "content", fetch => "all", keyfield => "int04", main_id => "=::300016", template_id => "225", int04 => "!=::99", int10 => 1, #available int09 => "is::null", #not Contributor-Archive }; my $station_rec = $dbt->fetch_record($dbh,$pref); #fetch all bikes my $pref_b = { table => "content", fetch => "all", keyfield => "barcode", barcode => ">::0", template_id => "205", archive => "is::null", #not Contributor-bikes }; my $bikes_rec = $dbt->fetch_record($dbh,$pref_b); my $bike_stat = {}; my $adr_stat = {}; #fetch contenttranspos my $pos_search = { table => "contenttranspos", fetch => "all", keyfield => "c_id", #int04 => "!=::99",#virtuel end-station int05 => "is::null",#not if sub workflow doc int06 => "!=::99",#virtuel start-station int29 => "$bike_type_id",#nodes.type_id int34 => "is::null",#not if staff start_itime => ">=::$start_itime", end_itime => "<::$end_itime", }; my $pos = $dbt->fetch_tablerecord($dbh,$pos_search); #print "fetching bookings: Start >= $start_itime End < $end_itime\n"; my @stations = ("$year-$month Mietmenge Rad/Station"); foreach my $int04_id (sort { $station_rec->{$a}->{int04} <=> $station_rec->{$b}->{int04} } keys (%$station_rec)){ push(@stations,$station_rec->{$int04_id}->{int04}); } #Statistik-occubike_station my $csv = Text::CSV_XS->new ({ binary => 1, sep_char => ";", eol => "\r\n" }); my $filename_fhda = "Statistik-occubike_station_$year-$month-$flotte.csv"; open my $fhda, ">", "$varenv{csv}/$filename_fhda" or die "$filename_fhda: $!\n"; $csv->print($fhda, \@stations);#Stations CSV header #Statistik-average_bike my $csv_average_bike = Text::CSV_XS->new ({ binary => 1, sep_char => ";", eol => "\r\n" }); my $filename_average_bike = "Statistik-average_bike_$year-$month-$flotte.csv"; open my $abike, ">", "$varenv{csv}/$filename_average_bike" or die "$filename_average_bike: $!\n"; my @average_bike = ("$year-$month Nutzung/Rad","Anzahl","Gesamt Std","Durchschnitt Std","Gesamt KM","Durchschnitt KM"); $csv_average_bike->print($abike, \@average_bike);#$average_bike CSV header #Statistik-average_user my $csv_average_user = Text::CSV_XS->new ({ binary => 1, sep_char => ";", eol => "\r\n" }); my $filename_average_user = "Statistik-average_user_$year-$month-$flotte.csv"; open my $auser, ">", "$varenv{csv}/$filename_average_user" or die "$filename_average_user: $!\n"; my @average_user = ("$year-$month Nutzung/Nutzer","Anzahl","Gesamt Std","Durchschnitt Std"); $csv_average_user->print($auser, \@average_user);#$average_user CSV header if(1==1){ my $pricing = {}; my $rental = {}; #loop bookings foreach my $c_id (sort { $pos->{$a}->{barcode} <=> $pos->{$b}->{barcode} } keys (%$pos)){ ($pricing->{$c_id},my $counting) = $pri->counting_rental(\%varenv,$pos->{$c_id}); if($pos->{$c_id}->{int10} == 1 && $pricing->{$c_id}->{rentalog}->{rental_minute_all} && $pricing->{$c_id}->{rentalog}->{rental_minute_all} > 0){ #print "$pos->{$c_id}->{barcode} --> rental_minute_all: $pricing->{$c_id}->{rentalog}->{rental_minute_all}\n"; if($pos->{$c_id}->{ca_id}){ #if($adr_one->{c_id}){ if(1==1){ $adr_stat->{$pos->{$c_id}->{ca_id}}->{c_id} = $pos->{$c_id}->{ca_id}; $adr_stat->{$pos->{$c_id}->{ca_id}}->{counter}++; $adr_stat->{$pos->{$c_id}->{ca_id}}->{minutes} += $pricing->{$c_id}->{rentalog}->{rental_minute_all}; $adr_stat->{$pos->{$c_id}->{ca_id}}->{hours} = $adr_stat->{$pos->{$c_id}->{ca_id}}->{minutes} / 60 if($adr_stat->{$pos->{$c_id}->{ca_id}}->{minutes}); $bike_stat->{$pos->{$c_id}->{barcode}}->{counter}++; $bike_stat->{$pos->{$c_id}->{barcode}}->{minutes} += $pricing->{$c_id}->{rentalog}->{rental_minute_all}; $bike_stat->{$pos->{$c_id}->{barcode}}->{hours} = $bike_stat->{$pos->{$c_id}->{barcode}}->{minutes} / 60 if($bike_stat->{$pos->{$c_id}->{barcode}}->{minutes}); $bike_stat->{$pos->{$c_id}->{barcode}}->{km} += $pos->{$c_id}->{int26} if($pos->{$c_id}->{int26}); foreach my $int04_id (sort { $station_rec->{$a}->{int04} <=> $station_rec->{$b}->{int04} } keys (%$station_rec)){ if(($pos->{$c_id}->{int06} && $station_rec->{$int04_id}->{int04}) && ($pos->{$c_id}->{int06} == $station_rec->{$int04_id}->{int04})){ $rental->{$pos->{$c_id}->{barcode}}->{$station_rec->{$int04_id}->{int04}}++;#counter } } } } } } #print Dumper($rental) . "\n"; #Durchschnittliche Gesamtnutzungsdauer pro NutzerIn"; foreach my $a_id (sort { $adr_stat->{$a}->{c_id} <=> $adr_stat->{$b}->{c_id} } keys(%$adr_stat)){ if($adr_stat->{$a_id}->{hours} > 0 && $adr_stat->{$a_id}->{counter} > 0){ my $hours = sprintf('%.2f',$adr_stat->{$a_id}->{hours}); my $average = sprintf('%.2f',$hours / $adr_stat->{$a_id}->{counter}); $hours =~ s/\./,/; $average =~ s/\./,/; my @average_user_line = ("Nutzer ID:$adr_stat->{$a_id}->{c_id}","$adr_stat->{$a_id}->{counter}","$hours","$average"); $csv_average_user->print($auser, \@average_user_line);#foreach user one line $sendref->{message} .= "Nutzer ID:$adr_stat->{$a_id}->{c_id}, $hours Std / $adr_stat->{$a_id}->{counter} Menge = $average Std im Durchschnitt\n"; } } #Generate bike/station CSV-lines foreach my $b_id (sort { $bikes_rec->{$a}->{barcode} <=> $bikes_rec->{$b}->{barcode} } keys(%$bikes_rec)){ if($bikes_rec->{$b_id}->{type_id} == $bike_type_id){ #Durchschnittliche Nutzungsdauer pro Rad my $km = $bike_stat->{$b_id}->{km} || 0; my $km_average = 0; my $hours = $bike_stat->{$b_id}->{hours} || 0; my $counter = $bike_stat->{$b_id}->{counter} || 0; my $average = 0; if($hours > 0){ $hours = sprintf('%.2f',$bike_stat->{$b_id}->{hours}); $average = sprintf('%.2f',$hours / $counter); $hours =~ s/\./,/; $average =~ s/\./,/; } if($km > 0){ $km = sprintf('%.2f',$bike_stat->{$b_id}->{km}); $km_average = sprintf('%.2f',$km / $counter); $km =~ s/\./,/; $km_average =~ s/\./,/; } my @average_bike_line = ("$bikes_rec->{$b_id}->{txt01} Nr. $b_id","$counter","$hours","$average","$km","$km_average"); $csv_average_bike->print($abike, \@average_bike_line);#foreach bike one line $sendref->{message} .= "$bikes_rec->{$b_id}->{txt01} Nr. $b_id, $hours Std / $counter Miete = $average Std im Durchschnitt\n"; my @bike_station_array = ("$bikes_rec->{$b_id}->{txt01}, Nr. $b_id"); my $i = 0; foreach my $int04_id (sort { $station_rec->{$a}->{int04} <=> $station_rec->{$b}->{int04} } keys (%$station_rec)){ $i++; if($rental->{$b_id}->{$int04_id}){ #print "bike: $b_id, station: $int04_id --> count: $rental->{$b_id}->{$int04_id}\n"; #print "-> Stations count: " . Dumper($rental->{$b_id}->{$int04_id}) . "\n"; $bike_station_array[$i] = $rental->{$b_id}->{$int04_id} || 0;#Stations count #print "--> Stations count: " . Dumper(\@bike_station_array) . "\n"; } } $csv->print($fhda, \@bike_station_array);#foreach bike one line } } }#end if