2021-12-30 12:05:56 +01:00
package Pricing ;
#
# SPDX-License-Identifier: AGPL-3.0-or-later
# Copyright (c) Rainer Gümpelein, TeilRad GmbH
#
use strict ;
use warnings ;
use POSIX ;
use CGI ; # only for debugging
use Scalar::Util qw( looks_like_number ) ;
use Lib::Config ;
use Mod::Libenz ;
use Mod::DBtank ;
use Mod::Callib ;
use Mod::Basework ;
use Data::Dumper ;
my $ cf = new Config ;
my $ lb = new Libenz ;
my $ dbt = new DBtank ;
my $ cal = new Callib ;
my $ bw = new Basework ;
sub new {
my $ class = shift ;
my $ self = { } ;
bless ( $ self , $ class ) ;
return $ self ;
}
my $ dbh = "" ;
sub only_first_free () {
my $ self = shift ;
my $ ctpos = shift ;
my % varenv = $ cf - > envonline ( ) ;
my $ pref = {
table = > "contenttrans" ,
table_pos = > "contenttranspos" ,
fetch = > "one" ,
template_id = > "218" , #Faktura tpl_id
ca_id = > "=::$ctpos->{ca_id}" ,
c_id = > "!=::$ctpos->{c_id}" ,
#txt10 => "IN::('available','canceled')",
int10 = > "IN::('1','6')" ,
"ct.close_time" = > "is::null" ,
} ;
$ pref = { %$ pref , time_range = > "start_time >= '$ctpos->{start_time}' and start_time < '$ctpos->{end_time}' and start_time != end_time" } ;
my $ record = $ dbt - > collect_post ( $ dbh , $ pref ) ;
return $ record ;
}
sub sharee_pricing () {
my $ self = shift ;
my $ ctpos = shift ;
my $ todo = shift ;
my % varenv = $ cf - > envonline ( ) ;
my $ today4db = strftime ( "%Y-%m-%d %H:%M:%S" , localtime ( time ) ) ;
my $ return = { } ;
my $ logging = { } ;
$ logging - > { ID } = "c_id:$ctpos->{c_id}/ct_id:$ctpos->{ct_id}/ca_id:$ctpos->{ca_id}" ;
my $ computed_end_time = $ ctpos - > { end_time } || $ today4db ;
$ computed_end_time = $ today4db if ( $ ctpos - > { int10 } && $ ctpos - > { int10 } == 3 ) ;
my ( $ start_datetime , $ end_datetime , $ s_up , $ e_up , $ hours ) = $ cal - > contenttranspos_dating ( $ ctpos - > { c_id } , $ ctpos - > { start_time } , "$computed_end_time" , "$today4db" , "" ) ;
$ logging - > { hours_input } = $ hours ;
$ logging - > { tariff } = "$ctpos->{txt04} - $ctpos->{int09}" ;
;
my $ bike_group = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}$ctpos->{int12}" || "" ;
my $ days_pricemax = $ ctpos - > { int17 } || 9 ;
$ logging - > { days_pricemax } = $ days_pricemax ;
my $ price = 2 ; #FIXME to real val. must be not 0
$ price = sprintf ( '%.2f' , $ ctpos - > { int02 } ) if ( $ ctpos - > { int02 } && $ ctpos - > { int02 } > 0 ) ;
my $ total = 0 ;
#my $days_pricemax = "4.5";#TINK max 9,- € bike/day depends on 2,- €/hour
#my $days_pricemax = 5; #KonRad max 15,- € bike/day depends on 3,- €/hour
my $ days_hour4price = $ days_pricemax / $ price ;
$ logging - > { days_hour4price } = $ days_hour4price ;
my $ real_hours = $ hours ;
if ( $ ctpos - > { int16 } && $ ctpos - > { int16 } > 0 ) { #z.b. 30 Min/Gratis --> 0.5
my $ ctpos_freed = $ self - > only_first_free ( $ ctpos ) ;
#Bsp 1h = 60min , 60*0,02 = 1,2min
if ( ! $ ctpos_freed - > { c_id } || $ real_hours <= 0.02 ) {
$ hours -= $ ctpos - > { int16 } ;
$ logging - > { hours_freed } = $ hours ;
} else {
$ logging - > { hours_freed } = "Not freed because of (!$ctpos_freed->{c_id} && $ctpos->{int16} || $real_hours <= 0.02)" ;
}
}
#If available then take saved hours
if ( $ ctpos - > { int10 } && $ ctpos - > { int10 } == 1 && $ todo eq "readonly" ) {
if ( $ ctpos - > { int03 } && $ ctpos - > { int03 } > 0 ) {
$ hours = $ ctpos - > { int03 } ;
$ total = $ hours * $ price if ( looks_like_number ( $ hours ) && looks_like_number ( $ price ) ) ;
} else {
$ hours = 0 ;
$ total = 0 ;
}
}
#jede angebrochene Std.
elsif ( looks_like_number ( $ hours ) && $ hours > 0 ) {
if ( $ days_hour4price > 0 && $ hours >= $ days_hour4price && $ hours <= 24 ) {
$ logging - > { _hours_lower24 } = "$days_hour4price > 0 && $hours >= $days_hour4price && $hours <= 24" ;
$ logging - > { __hours_lower24 } = $ hours ;
$ hours = $ days_hour4price ;
$ logging - > { hours_lower24 } = $ hours ;
}
elsif ( $ days_hour4price > 0 && $ hours >= 24 ) {
$ logging - > { hours_greate24 } = "$days_hour4price > 0 && $hours >= 24" ;
my $ days = $ hours / 24 ;
my $ days_int = $ days ;
my $ dez = 0 ;
( $ days_int , $ dez ) = split ( /\./ , $ days ) if ( $ days =~ /\.\d/ ) ;
my $ days_hour = $ days_int * 24 ;
my $ rest = $ hours - $ days_hour ;
$ rest = $ days_hour4price if ( $ rest > $ days_hour4price ) ;
$ hours = ( $ days_int * $ days_hour4price ) + $ rest ;
$ logging - > { hours_compute } = "$hours = ($days_int * $days_hour4price) + $rest" ;
}
$ logging - > { hours_preround } = $ hours ;
$ hours = $ lb - > round_half ( $ hours ) ;
$ logging - > { hours_postround } = $ hours ;
$ total = $ hours * $ price if ( looks_like_number ( $ hours ) && looks_like_number ( $ price ) ) ;
} else {
$ hours = 0 ;
}
$ total = sprintf ( '%.2f' , $ total ) ;
#Bsp 1h = 60min , 60*0,02 = 1,2min
$ hours = "0" if ( $ real_hours <= 0.02 ) ;
$ return - > { real_hours } = "$real_hours" ;
$ return - > { computed_hours } = "$hours" ;
$ return - > { unit_price } = "$price" ;
$ return - > { total_price } = "$total" ;
$ return - > { bike_group } = [ "$bike_group" ] ;
$ return - > { station } = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}$ctpos->{int04}" ; #TODO save with prefix
$ return - > { uri_operator } = "$varenv{wwwhost}" ; #TODO, should be DB select
$ return - > { bike } = "$dbt->{operator}->{$varenv{dbname}}->{oprefix}$ctpos->{barcode}" ;
$ return - > { state } = "$dbt->{copri_conf}->{bike_state}->{$ctpos->{int10}}" || "" ;
$ return - > { bike_charge } = "$ctpos->{int19}" if ( $ ctpos - > { int19 } ) ;
$ return - > { description } = "$ctpos->{txt01}" ;
$ return - > { request_time } = "$ctpos->{itime}" ;
$ return - > { start_time } = "$ctpos->{start_time}" ;
$ return - > { end_time } = "$computed_end_time" ;
$ return - > { system } = "Ilockit" || "" ; #FIXME
if ( $ ctpos - > { int11 } eq "2" ) {
#$return->{gps} = "$ctpos->{txt06}";#end_gps
( $ return - > { gps } - > { latitude } , $ return - > { gps } - > { longitude } ) = split ( /,/ , $ ctpos - > { txt06 } ) ;
#if($ctpos->{txt10} =~ /requested|occupied/)
if ( $ ctpos - > { int10 } == 2 || $ ctpos - > { int10 } == 3 ) {
$ return - > { tariff_description } - > { name } = "$ctpos->{txt04}" ;
$ return - > { tariff_description } - > { number } = "$ctpos->{int09}" ;
$ return - > { tariff_description } - > { eur_per_hour } = "$ctpos->{int02}" || "0" ;
$ return - > { tariff_description } - > { max_eur_per_day } = "$ctpos->{int17}" || "0" ;
$ return - > { tariff_description } - > { free_hours } = "$ctpos->{int16}" if ( $ ctpos - > { int16 } && $ ctpos - > { int16 } > 0 ) ;
$ return - > { tariff_description } - > { abo_eur_per_month } = "$ctpos->{int15}" if ( $ ctpos - > { int15 } && $ ctpos - > { int15 } > 0 ) ;
$ return - > { tariff_description } - > { track_info } = "Ich stimme der Speicherung (Tracking) meiner Fahrstrecke zwecks wissenschaftlicher Auswertung und Berechnung der CO2-Einsparung zu!" if ( $ ctpos - > { int25 } ) ;
$ return - > { tariff_description } - > { operator_agb } = "Mit der Mietrad Anmietung wird folgender Betreiber <a href='$varenv{wwwhost}/site/agb.html' target='_blank'>AGB</a> zugestimmt (als Demo sharee AGB)." if ( $ ctpos - > { ca_id } == 1842 || $ ctpos - > { ca_id } == 5781 ) ;
$ return - > { Ilockit_GUID } = "$ctpos->{txt17}" ;
$ return - > { Ilockit_ID } = "$ctpos->{txt18}" ;
#$return->{gps} = "$ctpos->{txt06}";#start_gps
( $ return - > { gps } - > { latitude } , $ return - > { gps } - > { longitude } ) = split ( /,/ , $ ctpos - > { txt06 } ) ;
$ return - > { lock_state } = "locked" if ( $ ctpos - > { int20 } == 1 ) ;
$ return - > { lock_state } = "unlocked" if ( $ ctpos - > { int20 } == 2 ) ;
2022-03-01 10:25:13 +01:00
$ return - > { lock_state } = "locking" if ( $ ctpos - > { int20 } == 3 ) ;
2021-12-30 12:05:56 +01:00
}
}
$ bw - > log ( "hour computed:" , $ logging , "" ) ;
return $ return ;
}
#CO2 calculator
#Bsp Berechnungen:
# Pkw:
# Distanz * CO2-Emission Pkw / 100 km
# 8.760 km * 20 kg CO2 / 100 km = 1.752 kg CO2
# Pedelec:
# Distanz * CO2-Emission Pedelec / 100 km
# 10.950 km * 0,546 kg CO2 / 100 km = 62 kg CO2
#
# Aus der Differenz zwischen der CO2-Emission Pkw und der CO2-Emission Pedelec ergibt sich das Einsparpotenzial:
# 1.752 kg CO2 – 62 kg CO2 = 1.690 kg CO2, also rund 1,7 t CO2 pro Jahr
#
sub co2calc {
my $ self = shift ;
my $ ctpos = shift ;
my $ co2diff = 0 ;
my $ co2pkw = $ ctpos - > { int26 } * 20 / 100 ;
my $ co2ped = $ ctpos - > { int26 } * 0.546 / 100 ;
$ co2diff = $ co2pkw - $ co2ped ;
$ co2diff = sprintf ( '%.2f' , $ co2diff ) ;
$ co2diff =~ s/\./,/ ;
return $ co2diff ;
}
#calculates sprit saving
sub sprit2calc {
my $ self = shift ;
my $ ctpos = shift ;
my $ einzel = $ ctpos - > { int02 } ;
my $ menge = $ ctpos - > { int03 } ;
my $ rabatt_val = $ ctpos - > { int07 } || 0 ;
my $ gesamt = 0 ;
if ( $ rabatt_val != 0 && $ einzel && $ menge ) {
my $ rabatt_eur = $ rabatt_val ;
#if int08 != 1 alias €
$ rabatt_eur = $ einzel * $ menge * $ rabatt_val / 100 if ( $ ctpos - > { int08 } != 1 ) ;
$ gesamt = $ einzel * $ menge - $ rabatt_eur ;
} elsif ( $ einzel && $ menge ) {
$ gesamt = $ einzel * $ menge ;
}
my $ sprit_price = 0 ;
$ sprit_price = $ ctpos - > { int26 } * 0.3 if ( $ ctpos - > { int26 } != 0 ) ;
$ sprit_price -= $ gesamt ;
$ sprit_price = sprintf ( '%.2f' , $ sprit_price ) ;
$ sprit_price =~ s/\./,/ ;
return $ sprit_price ;
}
#computes position price and rabatt
sub price2calc {
my $ self = shift ;
my $ ctpos = shift ;
my $ gesamt = 0 ;
my $ rabatt = "" ;
my $ einzel = $ ctpos - > { int02 } ;
my $ menge = $ ctpos - > { int03 } ;
my $ rabatt_val = $ ctpos - > { int07 } || 0 ;
if ( $ rabatt_val != 0 && $ einzel && $ menge ) {
my $ rabatt_eur = $ rabatt_val ;
#if int08 != 1 alias €
$ rabatt_eur = $ einzel * $ menge * $ rabatt_val / 100 if ( $ ctpos - > { int08 } != 1 ) ;
$ gesamt = $ einzel * $ menge - $ rabatt_eur ;
} elsif ( $ einzel && $ menge ) {
$ gesamt = $ einzel * $ menge ;
}
if ( $ ctpos - > { int07 } && $ ctpos - > { int07 } > 0 && $ menge > 0 ) {
$ rabatt = "-" . $ ctpos - > { int07 } ;
if ( $ ctpos - > { int08 } == 1 ) {
$ rabatt . = " €" ;
} else {
$ rabatt =~ s/\.00// ;
$ rabatt . = " %" ;
}
}
return ( $ gesamt , $ rabatt ) ;
}
1 ;