2023-04-24 14:49:30 +02:00
|
|
|
#!/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
|
2023-11-23 19:02:16 +01:00
|
|
|
int09 => "is::null", #Contributor-Archive
|
2023-04-24 14:49:30 +02:00
|
|
|
};
|
|
|
|
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",
|
2023-11-23 19:02:16 +01:00
|
|
|
archive => "is::null", #Contributor-bikes
|
2023-04-24 14:49:30 +02:00
|
|
|
};
|
|
|
|
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
|
2023-11-23 19:02:16 +01:00
|
|
|
start_itime => ">=::$start_itime",
|
|
|
|
end_itime => "<::$end_itime",
|
2023-04-24 14:49:30 +02:00
|
|
|
};
|
|
|
|
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)){
|
2023-11-23 19:02:16 +01:00
|
|
|
#if($bikes_rec->{$b_id}->{type_id} == $bike_type_id && $bikes_rec->{$b_id}->{node_name} !~ /Contributor/i){
|
|
|
|
if($bikes_rec->{$b_id}->{type_id} == $bike_type_id){
|
2023-04-24 14:49:30 +02:00
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
|