From 5f59a14bb8b7d0e12fd3afa96f5d59ccf0c21d92 Mon Sep 17 00:00:00 2001 From: Rene Krenn Date: Sun, 17 Jan 2016 19:51:33 +0100 Subject: [PATCH] MT#17261 rateomat test case for cdr splitting btw. it was difficult to find a setup to really make it split the cdrs, and not getting the "inconsistent rating profile fragements" error. so using RATEOMAT_SPLIT_PEAK_PARTS=1 has to be used with care definitely. Change-Id: If3e3376fd9cab7de31a3ace3e9e6fa1e1a0f9b12 --- t/Utils/Api.pm | 42 +++++--- t/Utils/Rateomat.pm | 33 ++++++ t/rateomat-balanceunderrun.t | 26 ++--- t/rateomat-catchup-discard.t | 44 ++++---- t/rateomat-catchup-intervals.t | 52 +++++----- t/rateomat-dst-transitions.t | 40 +++---- t/rateomat-negative-fees.t | 42 ++++---- t/rateomat-parallel.t | 32 +++--- t/rateomat-roaming.t | 18 ++-- t/rateomat-split-cdr.t | 184 +++++++++++++++++++++++++++++++++ 10 files changed, 374 insertions(+), 139 deletions(-) create mode 100644 t/rateomat-split-cdr.t diff --git a/t/Utils/Api.pm b/t/Utils/Api.pm index dce4259..90e148b 100644 --- a/t/Utils/Api.pm +++ b/t/Utils/Api.pm @@ -14,7 +14,8 @@ use Data::Dumper; my $uri = $ENV{CATALYST_SERVER} // 'https://127.0.0.1:443'; my $user = $ENV{API_USER} // 'administrator'; -my $pass = $ENV{API_USER} // 'administrator'; +my $pass = $ENV{API_PASS} // 'administrator'; +my $split_peak_parts = $ENV{RATEOMAT_SPLIT_PEAK_PARTS} // 0; require Exporter; our @ISA = qw(Exporter); @@ -560,11 +561,11 @@ sub _get_interval_start { sub _add_interval { my ($from,$interval_unit,$interval_value,$align_eom_dt) = @_; if ('minute' eq $interval_unit) { - return $from->clone->add(minutes => $interval_value); + return $from->clone->add(minutes => $interval_value); } elsif ('hour' eq $interval_unit) { return $from->clone->add(hours => $interval_value); } elsif ('day' eq $interval_unit) { - return $from->clone->add(days => $interval_value); + return $from->clone->add(days => $interval_value); } elsif ('week' eq $interval_unit) { return $from->clone->add(weeks => $interval_value); } elsif ('month' eq $interval_unit) { @@ -671,7 +672,7 @@ sub setup_subscriber { } sub setup_provider { - my ($domain_name,$rates,$networks) = @_; + my ($domain_name,$rates,$networks,$provider_rate) = @_; my $provider = {}; $provider->{contact} = create_systemcontact(); $provider->{contract} = create_contract( @@ -681,9 +682,22 @@ sub setup_provider { $provider->{reseller} = create_reseller( contract_id => $provider->{contract}->{id}, ); - $provider->{profile} = create_billing_profile( - reseller_id => $provider->{reseller}->{id}, - ); + if (defined $provider_rate) { + my $profile_fee = {}; + ($profile_fee->{profile}, + $profile_fee->{zone}, + $profile_fee->{fee}, + $profile_fee->{fees}) = _setup_fees($provider->{reseller}, + %$provider_rate + ); + $provider->{profile} = $profile_fee->{profile}; + $provider->{provider_fee} = $profile_fee; + } else { + ok(!$split_peak_parts,'provider rate required for split cdrs'); + $provider->{profile} = create_billing_profile( + reseller_id => $provider->{reseller}->{id}, + ); + } $provider->{contract} = update_item($provider->{contract}, billing_profile_id => $provider->{profile}->{id}, ); @@ -691,16 +705,16 @@ sub setup_provider { reseller_id => $provider->{reseller}->{id}, domain => $domain_name.'.', ); - $provider->{profiles} = []; + $provider->{subscriber_fees} = []; foreach my $rate (@$rates) { my $profile_fee = {}; ($profile_fee->{profile}, $profile_fee->{zone}, $profile_fee->{fee}, - $profile_fee->{fees}) = _setup_customer_fees($provider->{reseller}, + $profile_fee->{fees}) = _setup_fees($provider->{reseller}, %$rate ); - push(@{$provider->{profiles}},$profile_fee); + push(@{$provider->{subscriber_fees}},$profile_fee); } $provider->{networks} = []; foreach my $network_blocks (@$networks) { @@ -713,12 +727,16 @@ sub setup_provider { return $provider; } -sub _setup_customer_fees { +sub _setup_fees { my ($reseller,%params) = @_; my $prepaid = delete $params{prepaid}; + my $peaktime_weekdays = delete $params{peaktime_weekdays}; + my $peaktime_specials = delete $params{peaktime_special}; my $profile = create_billing_profile( reseller_id => $reseller->{id}, (defined $prepaid ? (prepaid => $prepaid) : ()), + (defined $peaktime_weekdays ? (peaktime_weekdays => $peaktime_weekdays) : ()), + (defined $peaktime_specials ? (peaktime_special => $peaktime_specials) : ()), ); my $zone = create_billing_zone( billing_profile_id => $profile->{id}, @@ -748,4 +766,4 @@ sub to_pretty_json { return JSON::to_json(shift, {pretty => 1}); # =~ s/(^\s*{\s*)|(\s*}\s*$)//rg =~ s/\n /\n/rg; } -1; \ No newline at end of file +1; diff --git a/t/Utils/Rateomat.pm b/t/Utils/Rateomat.pm index 704733c..f90cbd8 100644 --- a/t/Utils/Rateomat.pm +++ b/t/Utils/Rateomat.pm @@ -17,6 +17,7 @@ our @EXPORT_OK = qw( run_rateomat_threads create_cdrs get_cdrs + get_cdrs_by_call_id prepare_cdr check_cdr check_cdrs @@ -322,6 +323,20 @@ sub get_cdrs { return $result; } +sub get_cdrs_by_call_id { + my $call_id = shift; + my $result = []; + eval { + my $dbh = _connect_accounting_db(); + $result = _get_cdrs_by_callid($dbh,$call_id,1); + _disconnect_db($dbh); + }; + if ($@) { + diag($@); + } + return $result; +} + sub delete_cdrs { my $ids = shift; my $is_ary = 'ARRAY' eq ref $ids; @@ -415,6 +430,24 @@ sub _get_cdrs { return $cdrs; } +sub _get_cdrs_by_callid { + my ($dbh,$call_id,$created) = @_; + my $cdrs = []; + if ($dbh) { + my $sth = $dbh->prepare('SELECT * FROM accounting.cdr WHERE call_id = ? ORDER BY id') + or die("Error preparing select cdrs by call id statement: ".$dbh->errstr); + $sth->execute($call_id); + $cdrs = $sth->fetchall_arrayref({}); + $sth->finish(); + if ($created) { + foreach my $cdr (@$cdrs) { + $cdr_map{$cdr->{id}} = $cdr; + } + } + } + return $cdrs; +} + sub _insert { my ($dbh,$table,$values) = @_; my $id = undef; diff --git a/t/rateomat-balanceunderrun.t b/t/rateomat-balanceunderrun.t index 2a730e9..72f20db 100644 --- a/t/rateomat-balanceunderrun.t +++ b/t/rateomat-balanceunderrun.t @@ -8,14 +8,14 @@ use Test::More; Utils::Api::set_time(Utils::Api::get_now->subtract(months => 5)); #provider contract needs to be created in the past as well: my $provider = create_provider(); -my $callee = Utils::Api::setup_subscriber($provider,$provider->{profiles}->[0]->{profile},undef,{ cc => 888, ac => '2', sn => '' }); +my $callee = Utils::Api::setup_subscriber($provider,$provider->{subscriber_fees}->[0]->{profile},undef,{ cc => 888, ac => '2', sn => '' }); Utils::Api::set_time(); my $amount = 5; -my $costs_initial = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval})/100.0; -my $costs_underrun = ($provider->{profiles}->[1]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[1]->{fee}->{onpeak_init_interval})/100.0; +my $costs_initial = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval})/100.0; +my $costs_underrun = ($provider->{subscriber_fees}->[1]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[1]->{fee}->{onpeak_init_interval})/100.0; my $lock_level = 4; { @@ -24,13 +24,13 @@ my $lock_level = 4; my $profiles_setup = Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: ], [ #underrun: - $provider->{profiles}->[2]->{profile} + $provider->{subscriber_fees}->[2]->{profile} ], balance_interval_start_mode => 'create', balance_interval_value => 30, @@ -64,11 +64,11 @@ my $lock_level = 4; { start => Utils::Api::datetime_to_string($begin->truncate(to => 'day')), stop => Utils::Api::datetime_to_string($begin->add(days => 30)->clone->subtract(seconds => 1)), cash => $amount, - profile => $provider->{profiles}->[0]->{profile}->{id} }, + profile => $provider->{subscriber_fees}->[0]->{profile}->{id} }, { start => Utils::Api::datetime_to_string($begin), stop => Utils::Api::datetime_to_string($begin->add(days => 30)->clone->subtract(seconds => 1)), cash => 0, - profile => $provider->{profiles}->[2]->{profile}->{id}}, + profile => $provider->{subscriber_fees}->[2]->{profile}->{id}}, ]); is(Utils::Api::get_subscriber_preferences($caller->{subscriber})->{lock},$lock_level,$label.'subscriber is locked now'); is(Utils::Rateomat::get_usr_preferences($caller->{subscriber},'prepaid')->[0]->{value},1,$label.'subscriber is prepaid now'); @@ -81,13 +81,13 @@ my $lock_level = 4; my $profiles_setup = Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: ], [ #underrun: - $provider->{profiles}->[1]->{profile} + $provider->{subscriber_fees}->[1]->{profile} ], balance_interval_start_mode => 'topup', balance_interval_value => 30, @@ -123,7 +123,7 @@ my $lock_level = 4; { start => '~'.Utils::Api::datetime_to_string($begin), stop => Utils::Api::datetime_to_string(Utils::Api::infinite_future()), cash => $amount - $costs_initial - $costs_underrun, - profile => $provider->{profiles}->[0]->{profile}->{id} }, + profile => $provider->{subscriber_fees}->[0]->{profile}->{id} }, ]); is(Utils::Api::get_subscriber_preferences($caller->{subscriber})->{lock},$lock_level,$label.'subscriber is locked now'); } @@ -170,4 +170,4 @@ sub create_provider { [ #billing networks: ] ); -} \ No newline at end of file +} diff --git a/t/rateomat-catchup-discard.t b/t/rateomat-catchup-discard.t index 7f5097d..3518878 100644 --- a/t/rateomat-catchup-discard.t +++ b/t/rateomat-catchup-discard.t @@ -9,14 +9,14 @@ use Storable qw(); Utils::Api::set_time(Utils::Api::get_now->subtract(months => 5)); #provider contract needs to be created in the past as well: my $provider = create_provider(); -my $callee = Utils::Api::setup_subscriber($provider,$provider->{profiles}->[0]->{profile},undef,{ cc => 888, ac => '2', sn => '' }); +my $callee = Utils::Api::setup_subscriber($provider,$provider->{subscriber_fees}->[0]->{profile},undef,{ cc => 888, ac => '2', sn => '' }); Utils::Api::set_time(); my $amount = 5; -my $costs = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval})/100.0; -my $underrun_costs = ($provider->{profiles}->[1]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[1]->{fee}->{onpeak_init_interval})/100.0; +my $costs = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval})/100.0; +my $underrun_costs = ($provider->{subscriber_fees}->[1]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[1]->{fee}->{onpeak_init_interval})/100.0; my $interval_days = 30; my $timely_days = $interval_days / 3; @@ -26,7 +26,7 @@ foreach my $start_mode ('create','1st') { my $begin = Utils::Api::get_now->subtract(days => (3 * $interval_days + 1)); my $profiles_setup = Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: @@ -162,16 +162,16 @@ foreach my $carry_over_mode ('carry_over','carry_over_timely') { @cash_values = ( [ cash => $amount - $costs, debit => 0 ], [ cash => $amount - $costs ], [ cash => 0, debit => $underrun_costs ] ) if 'carry_over' eq $carry_over_mode; @cash_values = ( [ cash => $amount - $costs, debit => 0 ], [ cash => 0, debit => $underrun_costs ], [ cash => 0, debit => $underrun_costs ] ) if 'carry_over_timely' eq $carry_over_mode; foreach my $start_mode ('topup','topup_interval') { - + my $profiles_setup = Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: - + ], [ #underrun: - $provider->{profiles}->[1]->{profile} + $provider->{subscriber_fees}->[1]->{profile} ], balance_interval_start_mode => $start_mode, balance_interval_value => $interval_days, @@ -185,30 +185,30 @@ foreach my $carry_over_mode ('carry_over','carry_over_timely') { underrun_profile_threshold => 1, underrun_lock_level => 4, )->{package}; - + my $label = $start_mode . '/' . $carry_over_mode .': '; my $i = 0; - + foreach my $begin (Utils::Api::get_now->subtract(days => ($interval_days / 2)), Utils::Api::get_now->subtract(days => (1.5*$interval_days)), Utils::Api::get_now->subtract(days => (2.5*$interval_days))) { - + Utils::Api::set_time($begin); - + my $caller = Utils::Api::setup_subscriber($provider,$profiles_setup,$amount,{ cc => 888, ac => '1', sn => '' }); is(Utils::Api::get_subscriber_preferences($caller->{subscriber})->{lock},undef,$label.'subscriber is not locked initially'); is(Utils::Rateomat::get_usr_preferences($caller->{subscriber},'prepaid')->[0],undef,$label.'subscriber is not prepaid initially'); - + Utils::Api::set_time(); - + my $call_time = Utils::Api::get_now->subtract(minutes => 3); - + my @cdr_ids = map { $_->{id}; } @{ Utils::Rateomat::create_cdrs([ Utils::Rateomat::prepare_cdr($caller->{subscriber},undef,$caller->{reseller}, $callee->{subscriber},undef,$callee->{reseller}, '192.168.0.1',$call_time->epoch,1), ]) }; - + if (ok((scalar @cdr_ids) > 0 && Utils::Rateomat::run_rateomat(),'rate-o-mat executed')) { ok(Utils::Rateomat::check_cdrs('', map { $_ => { id => $_, rating_status => 'ok', }; } @cdr_ids @@ -222,13 +222,13 @@ foreach my $carry_over_mode ('carry_over','carry_over_timely') { is(Utils::Api::get_subscriber_preferences($caller->{subscriber})->{lock},4,$label.'subscriber is locked now'); is(Utils::Rateomat::get_usr_preferences($caller->{subscriber},'prepaid')->[0]->{value},1,$label.'subscriber is prepaid now'); } - + } $i++; } } } - + done_testing(); exit; @@ -255,7 +255,7 @@ sub create_provider { offpeak_init_interval => 60, offpeak_follow_rate => 2, offpeak_follow_interval => 30, - }, + }, ], [ #billing networks: ] @@ -267,4 +267,4 @@ sub set_cash { $interval = Storable::dclone($interval); $interval->{cash} = $cash; return $interval; -} \ No newline at end of file +} diff --git a/t/rateomat-catchup-intervals.t b/t/rateomat-catchup-intervals.t index ad88bb0..9d9e8cc 100644 --- a/t/rateomat-catchup-intervals.t +++ b/t/rateomat-catchup-intervals.t @@ -16,7 +16,7 @@ use Data::Dumper; my $provider = create_provider(); my $balance = 5; - my $profiles_setup = $provider->{profiles}->[0]->{profile}; + my $profiles_setup = $provider->{subscriber_fees}->[0]->{profile}; my $caller = Utils::Api::setup_subscriber($provider,$profiles_setup,$balance,{ cc => 888, ac => '1', sn => '' }); my $callee = Utils::Api::setup_subscriber($provider,$profiles_setup,$balance,{ cc => 888, ac => '2', sn => '' }); @@ -45,8 +45,8 @@ use Data::Dumper; rating_status => 'ok', }, ),'cdrs were all processed'); - my $costs = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval})/100.0; + my $costs = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval})/100.0; Utils::Api::check_interval_history('',$caller->{customer}->{id},[ { start => Utils::Api::datetime_to_string($begin->truncate(to => 'month')), stop => Utils::Api::datetime_to_string($begin->add(months => 1)->clone->subtract(seconds => 1)), @@ -84,7 +84,7 @@ use Data::Dumper; Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: @@ -137,8 +137,8 @@ use Data::Dumper; rating_status => 'ok', }, ),'cdrs were all processed'); - my $costs = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval})/100.0; + my $costs = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval})/100.0; my $label = $start_mode . '/' . $unit . ': '; $stats{$label} = ($t2 - $t1) . ' secs'; my $balance_intervals = Utils::Api::get_interval_history($label,$caller->{customer}->{id}); @@ -207,7 +207,7 @@ use Data::Dumper; Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: @@ -222,10 +222,10 @@ use Data::Dumper; ); my $call_minutes = 3*60; - my $amount = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval} + - $provider->{profiles}->[0]->{fee}->{onpeak_follow_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_follow_interval} * ($call_minutes - 1))/100.0; + my $amount = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval} + + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_interval} * ($call_minutes - 1))/100.0; my $profiles_setup = $provider->{packages}->[0]->{package}; my $caller = Utils::Api::setup_subscriber($provider,$profiles_setup,undef,{ cc => 888, ac => '1', sn => '' }); my $callee = Utils::Api::setup_subscriber($provider,$profiles_setup,undef,{ cc => 888, ac => '2', sn => '' }); @@ -254,12 +254,12 @@ use Data::Dumper; shift(@$balance_intervals); is(scalar @$balance_intervals,4,$label."number of balance intervals ".(scalar @$balance_intervals)." = 4"); my @minutes_per_interval = (44,60,60,15); - my $costs = $provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval}; + my $costs = $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval}; for (my $i = 0; $i < (scalar @$balance_intervals); $i++) { my $interval = $balance_intervals->[$i]; - $costs += $provider->{profiles}->[0]->{fee}->{onpeak_follow_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_follow_interval} * $minutes_per_interval[$i]; + $costs += $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_interval} * $minutes_per_interval[$i]; if ($i < ((scalar @$balance_intervals) - 1)) { ok(is_approx($interval->{cash_balance},($amount*100-$costs)/100,1.2),$label."interval cash balance $interval->{cash_balance} ~ ".($amount*100-$costs)/100); } else { @@ -280,7 +280,7 @@ use Data::Dumper; Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: @@ -295,10 +295,10 @@ use Data::Dumper; ); my $call_minutes = 3; - my $amount = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval} + - $provider->{profiles}->[0]->{fee}->{onpeak_follow_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_follow_interval} * ($call_minutes*60 - 1))/100.0; + my $amount = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval} + + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_interval} * ($call_minutes*60 - 1))/100.0; my $profiles_setup = $provider->{packages}->[0]->{package}; my $caller = Utils::Api::setup_subscriber($provider,$profiles_setup,undef,{ cc => 888, ac => '1', sn => '' }); my $callee = Utils::Api::setup_subscriber($provider,$profiles_setup,undef,{ cc => 888, ac => '2', sn => '' }); @@ -328,13 +328,13 @@ use Data::Dumper; my $total_costs = 0; for (my $i = 0; $i < scalar @$balance_intervals; $i++) { my $interval = $balance_intervals->[$i]; - my $costs = ($i > 0 ? ($i < $call_minutes ? $provider->{profiles}->[0]->{fee}->{onpeak_follow_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_follow_interval} : 0) : - $provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval}); + my $costs = ($i > 0 ? ($i < $call_minutes ? $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_follow_interval} : 0) : + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval}); $total_costs += $costs; is($interval->{cash_balance},($amount*100-$total_costs)/100, $label."interval cash balance $interval->{cash_balance} is " . ($amount*100-$total_costs)/100); - } + } } } @@ -365,4 +365,4 @@ sub create_provider { [ #billing networks: ] ); -} \ No newline at end of file +} diff --git a/t/rateomat-dst-transitions.t b/t/rateomat-dst-transitions.t index 4e759e9..48c3979 100644 --- a/t/rateomat-dst-transitions.t +++ b/t/rateomat-dst-transitions.t @@ -7,22 +7,22 @@ use Test::More; if ('Europe/Vienna' eq Utils::Api::get_now->time_zone->name) { Utils::Api::set_time(Utils::Api::datetime_from_string('2015-03-01 00:00:00')); - + my $provider = create_provider(); my $amount = 5; - my $callee = Utils::Api::setup_subscriber($provider,$provider->{profiles}->[0]->{profile},undef,{ cc => 888, ac => '2', sn => '' }); - my $costs_initial = ($provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval})/100.0; + my $callee = Utils::Api::setup_subscriber($provider,$provider->{subscriber_fees}->[0]->{profile},undef,{ cc => 888, ac => '2', sn => '' }); + my $costs_initial = ($provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval})/100.0; my $profiles_setup = Utils::Api::setup_package($provider, [ #initial: - $provider->{profiles}->[0]->{profile} + $provider->{subscriber_fees}->[0]->{profile} ], [ #topup: ], [ #underrun: - + ], balance_interval_start_mode => 'create', balance_interval_value => 1, @@ -30,25 +30,25 @@ if ('Europe/Vienna' eq Utils::Api::get_now->time_zone->name) { carry_over_mode => 'carry_over', initial_balance => $amount*100, )->{package}; - + { my $dt = Utils::Api::datetime_from_string('2015-03-29 01:26:00'); ok(!$dt->is_dst(),Utils::Api::datetime_to_string($dt)." is not in daylight saving time (winter)"); Utils::Api::set_time($dt); my $caller = Utils::Api::setup_subscriber($provider,$profiles_setup,undef,{ cc => 888, ac => '1', sn => '' }); - + $dt = Utils::Api::datetime_from_string('2015-03-29 03:26:00'); ok($dt->is_dst(),Utils::Api::datetime_to_string($dt)." is in daylight saving time (summer)"); Utils::Api::set_time($dt); - + my $now = Utils::Api::get_now(); - + my @cdr_ids = map { $_->{id}; } @{ Utils::Rateomat::create_cdrs([ Utils::Rateomat::prepare_cdr($caller->{subscriber},undef,$caller->{reseller}, $callee->{subscriber},undef,$callee->{reseller}, '192.168.0.1',$now->epoch,1), ]) }; - + if (ok((scalar @cdr_ids) > 0 && Utils::Rateomat::run_rateomat(),'rate-o-mat executed')) { ok(Utils::Rateomat::check_cdrs('', map { $_ => { id => $_, rating_status => 'ok', }; } @cdr_ids @@ -68,19 +68,19 @@ if ('Europe/Vienna' eq Utils::Api::get_now->time_zone->name) { ok($dt->is_dst(),Utils::Api::datetime_to_string($dt)." is in daylight saving time (summer)"); Utils::Api::set_time($dt); my $caller = Utils::Api::setup_subscriber($provider,$profiles_setup,undef,{ cc => 888, ac => '1', sn => '' }); - + $dt = Utils::Api::datetime_from_string('2015-10-25 03:26:00'); ok(!$dt->is_dst(),Utils::Api::datetime_to_string($dt)." is not in daylight saving time (winter)"); Utils::Api::set_time($dt); - + my $now = Utils::Api::get_now(); - + my @cdr_ids = map { $_->{id}; } @{ Utils::Rateomat::create_cdrs([ Utils::Rateomat::prepare_cdr($caller->{subscriber},undef,$caller->{reseller}, $callee->{subscriber},undef,$callee->{reseller}, '192.168.0.1',$now->epoch,1), ]) }; - + if (ok((scalar @cdr_ids) > 0 && Utils::Rateomat::run_rateomat(),'rate-o-mat executed')) { ok(Utils::Rateomat::check_cdrs('', map { $_ => { id => $_, rating_status => 'ok', }; } @cdr_ids @@ -93,14 +93,14 @@ if ('Europe/Vienna' eq Utils::Api::get_now->time_zone->name) { { start => '2015-10-25 03:00:00', stop => '2015-10-25 03:59:59', cash => $amount - $costs_initial }, ]); } - } - + } + Utils::Api::set_time(); - + } else { diag("time zone '" . Utils::Api::get_now->time_zone->name . "', skipping DST test"); } - + done_testing(); exit; @@ -121,4 +121,4 @@ sub create_provider { [ #billing networks: ] ); -} \ No newline at end of file +} diff --git a/t/rateomat-negative-fees.t b/t/rateomat-negative-fees.t index df7abfe..13fce2a 100644 --- a/t/rateomat-negative-fees.t +++ b/t/rateomat-negative-fees.t @@ -14,7 +14,7 @@ my $tb = Text::Table->new("request", "response"); my ($req,$res) = @_; if ($tb) { my $dtf = DateTime::Format::Strptime->new( - pattern => '%F %T', + pattern => '%F %T', ); #$tb->add(wrap('',"\t",$tb_cnt . ".\t" . $label . ":"),''); my $http_cmd = $req->method . " " . $req->uri; @@ -28,7 +28,7 @@ my $tb = Text::Table->new("request", "response"); my $res_data; eval { $res_data = JSON::from_json($res->decoded_content); - }; + }; if ($res_data) { $res_data = Storable::dclone($res_data); delete $res_data->{"_links"}; @@ -37,44 +37,44 @@ my $tb = Text::Table->new("request", "response"); $tb->add($req_data ? Utils::Api::to_pretty_json($req_data) : '', ''); } #$tb_cnt++; - }; + }; }; { my $provider = create_provider(); - my $profile = $provider->{profiles}->[0]->{profile}; + my $profile = $provider->{subscriber_fees}->[0]->{profile}; my $balance = 5; my $caller = Utils::Api::setup_subscriber($provider,$profile,$balance,{ cc => 888, ac => '1', sn => '' }); my $callee = Utils::Api::setup_subscriber($provider,$profile,$balance,{ cc => 888, ac => '2', sn => '' }); - my $caller_costs = ($provider->{profiles}->[0]->{fees}->[0]->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fees}->[0]->{onpeak_init_interval} + - $provider->{profiles}->[0]->{fees}->[0]->{onpeak_follow_rate} * - $provider->{profiles}->[0]->{fees}->[0]->{onpeak_follow_interval})/100.0; - my $callee_costs = ($provider->{profiles}->[0]->{fees}->[1]->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fees}->[1]->{onpeak_init_interval} + - $provider->{profiles}->[0]->{fees}->[1]->{onpeak_follow_rate} * - $provider->{profiles}->[0]->{fees}->[1]->{onpeak_follow_interval})/100.0; #negative! - + my $caller_costs = ($provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_init_interval} + + $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_follow_rate} * + $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_follow_interval})/100.0; + my $callee_costs = ($provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_init_interval} + + $provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_follow_rate} * + $provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_follow_interval})/100.0; #negative! + my $now = Utils::Api::get_now(); my @cdr_ids = map { $_->{id}; } @{ Utils::Rateomat::create_cdrs([ Utils::Rateomat::prepare_cdr($caller->{subscriber},undef,$caller->{reseller}, $callee->{subscriber},undef,$callee->{reseller}, '192.168.0.1',$now->epoch,61), ]) }; - + if (ok((scalar @cdr_ids) > 0 && Utils::Rateomat::run_rateomat(),'rate-o-mat executed')) { ok(Utils::Rateomat::check_cdrs('', map { $_ => { id => $_, rating_status => 'ok', }; } @cdr_ids ),'cdrs were all processed'); Utils::Api::check_interval_history('negative fees - caller',$caller->{customer}->{id},[ { cash => $balance - $caller_costs, - profile => $provider->{profiles}->[0]->{profile}->{id} }, + profile => $provider->{subscriber_fees}->[0]->{profile}->{id} }, ]); Utils::Api::check_interval_history('negative fees - callee',$callee->{customer}->{id},[ { cash => $balance - $callee_costs, - profile => $provider->{profiles}->[0]->{profile}->{id} }, - ]); - } + profile => $provider->{subscriber_fees}->[0]->{profile}->{id} }, + ]); + } } @@ -110,10 +110,10 @@ sub create_provider { offpeak_init_interval => 60, offpeak_follow_rate => -1*1, offpeak_follow_interval => 30, - }, - ]}, + }, + ]}, ], [ #billing networks: ] ); -} \ No newline at end of file +} diff --git a/t/rateomat-parallel.t b/t/rateomat-parallel.t index d9a0832..e93f8a2 100644 --- a/t/rateomat-parallel.t +++ b/t/rateomat-parallel.t @@ -13,39 +13,39 @@ use Test::More; #{ # my $provider = create_provider(); -# my $profile = $provider->{profiles}->[0]->{profile}; +# my $profile = $provider->{subscriber_fees}->[0]->{profile}; # my $balance = 5; # my $caller = Utils::Api::setup_subscriber($provider,$profile,$balance,{ cc => 888, ac => '1', sn => '' }); # my $callee = Utils::Api::setup_subscriber($provider,$profile,$balance,{ cc => 888, ac => '2', sn => '' }); -# my $caller_costs = ($provider->{profiles}->[0]->{fees}->[0]->{onpeak_init_rate} * -# $provider->{profiles}->[0]->{fees}->[0]->{onpeak_init_interval} + -# $provider->{profiles}->[0]->{fees}->[0]->{onpeak_follow_rate} * -# $provider->{profiles}->[0]->{fees}->[0]->{onpeak_follow_interval})/100.0; -# my $callee_costs = ($provider->{profiles}->[0]->{fees}->[1]->{onpeak_init_rate} * -# $provider->{profiles}->[0]->{fees}->[1]->{onpeak_init_interval} + -# $provider->{profiles}->[0]->{fees}->[1]->{onpeak_follow_rate} * -# $provider->{profiles}->[0]->{fees}->[1]->{onpeak_follow_interval})/100.0; #negative! -# +# my $caller_costs = ($provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_init_rate} * +# $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_init_interval} + +# $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_follow_rate} * +# $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_follow_interval})/100.0; +# my $callee_costs = ($provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_init_rate} * +# $provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_init_interval} + +# $provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_follow_rate} * +# $provider->{subscriber_fees}->[0]->{fees}->[1]->{onpeak_follow_interval})/100.0; #negative! +# # my $now = Utils::Api::get_now(); # my @cdr_ids = map { $_->{id}; } @{ Utils::Rateomat::create_cdrs([ # Utils::Rateomat::prepare_cdr($caller->{subscriber},undef,$caller->{reseller}, # $callee->{subscriber},undef,$callee->{reseller}, # '192.168.0.1',$now->epoch,61), # ]) }; -# +# # if (ok((scalar @cdr_ids) > 0 && Utils::Rateomat::run_rateomat(),'rate-o-mat executed')) { # ok(Utils::Rateomat::check_cdrs('', # map { $_ => { id => $_, rating_status => 'ok', }; } @cdr_ids # ),'cdrs were all processed'); # Utils::Api::check_interval_history('negative fees - caller',$caller->{customer}->{id},[ # { cash => $balance - $caller_costs, -# profile => $provider->{profiles}->[0]->{profile}->{id} }, +# profile => $provider->{subscriber_fees}->[0]->{profile}->{id} }, # ]); # Utils::Api::check_interval_history('negative fees - callee',$callee->{customer}->{id},[ # { cash => $balance - $callee_costs, -# profile => $provider->{profiles}->[0]->{profile}->{id} }, -# ]); -# } +# profile => $provider->{subscriber_fees}->[0]->{profile}->{id} }, +# ]); +# } # #} @@ -71,4 +71,4 @@ sub create_provider { [ #billing networks: ] ); -} \ No newline at end of file +} diff --git a/t/rateomat-roaming.t b/t/rateomat-roaming.t index 53c8905..8f3f5be 100644 --- a/t/rateomat-roaming.t +++ b/t/rateomat-roaming.t @@ -71,9 +71,9 @@ my $provider = Utils::Api::setup_provider('test.com', my $balance = 5; my $profiles_setup = [ - $provider->{profiles}->[0]->{profile}, - [ $provider->{profiles}->[1]->{profile}, $provider->{networks}->[0] ], - [ $provider->{profiles}->[2]->{profile}, $provider->{networks}->[1] ], + $provider->{subscriber_fees}->[0]->{profile}, + [ $provider->{subscriber_fees}->[1]->{profile}, $provider->{networks}->[0] ], + [ $provider->{subscriber_fees}->[2]->{profile}, $provider->{networks}->[1] ], ]; my $caller1 = Utils::Api::setup_subscriber($provider,$profiles_setup,$balance,{ cc => 888, ac => '1', sn => '' }); my $caller2 = Utils::Api::setup_subscriber($provider,$profiles_setup,$balance,{ cc => 888, ac => '1', sn => '' }); @@ -111,16 +111,16 @@ if (ok((scalar @cdr_ids) > 0 && Utils::Rateomat::run_rateomat(),'rate-o-mat exec }, ),'cdrs were all processed'); Utils::Api::check_interval_history('',$caller1->{customer}->{id},[ - { cash => (100.0 * $balance - $provider->{profiles}->[0]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[0]->{fee}->{onpeak_init_interval})/100.0 }, + { cash => (100.0 * $balance - $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[0]->{fee}->{onpeak_init_interval})/100.0 }, ]); Utils::Api::check_interval_history('',$caller2->{customer}->{id},[ - { cash => (100.0 * $balance - $provider->{profiles}->[1]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[1]->{fee}->{onpeak_init_interval})/100.0 }, + { cash => (100.0 * $balance - $provider->{subscriber_fees}->[1]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[1]->{fee}->{onpeak_init_interval})/100.0 }, ]); Utils::Api::check_interval_history('',$caller3->{customer}->{id},[ - { cash => (100.0 * $balance - $provider->{profiles}->[2]->{fee}->{onpeak_init_rate} * - $provider->{profiles}->[2]->{fee}->{onpeak_init_interval})/100.0 }, + { cash => (100.0 * $balance - $provider->{subscriber_fees}->[2]->{fee}->{onpeak_init_rate} * + $provider->{subscriber_fees}->[2]->{fee}->{onpeak_init_interval})/100.0 }, ]); } diff --git a/t/rateomat-split-cdr.t b/t/rateomat-split-cdr.t new file mode 100644 index 0000000..7c34780 --- /dev/null +++ b/t/rateomat-split-cdr.t @@ -0,0 +1,184 @@ + +use strict; + +use Utils::Api qw(); +use Utils::Rateomat qw(); +use Test::More; + +#THIS TEST CASE REQUIRES RATEOMAT_SPLIT_PEAK_PARTS=1 ! + +#use Text::Table; +#use Text::Wrap; +#use Storable; +#use DateTime::Format::Strptime; +#my $tb = Text::Table->new("request", "response"); +#*Utils::Api::log_request = sub { +# my ($req,$res) = @_; +# if ($tb) { +# my $dtf = DateTime::Format::Strptime->new( +# pattern => '%F %T', +# ); +# #$tb->add(wrap('',"\t",$tb_cnt . ".\t" . $label . ":"),''); +# my $http_cmd = $req->method . " " . $req->uri; +# $http_cmd =~ s/\?/?\n/; +# $tb->add($http_cmd,' ... at ' . $dtf->format_datetime(Utils::Api::get_now())); +# $tb->add("Request","Response"); +# my $req_data; +# eval { +# $req_data = JSON::from_json($req->decoded_content); +# }; +# my $res_data; +# eval { +# $res_data = JSON::from_json($res->decoded_content); +# }; +# if ($res_data) { +# $res_data = Storable::dclone($res_data); +# delete $res_data->{"_links"}; +# $tb->add($req_data ? Utils::Api::to_pretty_json($req_data) : '', Utils::Api::to_pretty_json($res_data)); +# } else { +# $tb->add($req_data ? Utils::Api::to_pretty_json($req_data) : '', ''); +# } +# #$tb_cnt++; +# }; +#}; + +{ + + my $call_minutes = 10; #divisible by 2 + my $date = Utils::Api::get_now()->ymd(); + my $t = Utils::Api::datetime_from_string($date . ' 07:30:00'); + Utils::Api::set_time($t); + my $provider = create_provider($date,$call_minutes); + my $profile = $provider->{subscriber_fees}->[0]->{profile}; + my $balance = 0; #no balances, for correct source_customer_cost + my $caller = Utils::Api::setup_subscriber($provider,$profile,$balance,{ cc => 888, ac => '1', sn => '' }); + my $callee = Utils::Api::setup_subscriber($provider,$profile,$balance,{ cc => 888, ac => '2', sn => '' }); + my $caller_costs = $provider->{subscriber_fees}->[0]->{fees}->[0]->{offpeak_init_rate} * 60 + + $provider->{subscriber_fees}->[0]->{fees}->[0]->{onpeak_follow_rate} * 60 * int(($call_minutes - 1) / 2 + 0.99) + + $provider->{subscriber_fees}->[0]->{fees}->[0]->{offpeak_follow_rate} * 60 * int(($call_minutes - 1) / 2); + my $caller_provider_costs = $provider->{provider_fee}->{fees}->[0]->{offpeak_init_rate} * 60 + + $provider->{provider_fee}->{fees}->[0]->{onpeak_follow_rate} * 60 * int(($call_minutes - 1) / 2 + 0.99) + + $provider->{provider_fee}->{fees}->[0]->{offpeak_follow_rate} * 60 * int(($call_minutes - 1) / 2); + $t = Utils::Api::datetime_from_string($date . ' 07:59:50'); + Utils::Api::set_time(); + my $cdr = Utils::Rateomat::create_cdrs([ + Utils::Rateomat::prepare_cdr($caller->{subscriber},undef,$caller->{reseller}, + $callee->{subscriber},undef,$callee->{reseller}, + '192.168.0.1',$t->epoch,$call_minutes*60), + ])->[0]; + + my %cdr_id_map = (); + my $onpeak = 0; #call starts offpeak + my $i = 1; + while (defined $cdr && ok(Utils::Rateomat::run_rateomat(),'rate-o-mat executed')) { + $cdr = Utils::Rateomat::get_cdrs($cdr->{id}); + $cdr_id_map{$cdr->{id}} = $cdr; + Utils::Rateomat::check_cdr('cdr was processed: ',$cdr->{id},{ rating_status => 'ok' }); + Utils::Rateomat::check_cdr('cdr is fragmented: ',$cdr->{id},{ is_fragmented => '1' }); + Utils::Rateomat::check_cdr('cdr is reseller onpeak: ',$cdr->{id},{ frag_reseller_onpeak => "$onpeak" }); + Utils::Rateomat::check_cdr('cdr is customer onpeak: ',$cdr->{id},{ frag_customer_onpeak => "$onpeak" }); + Utils::Rateomat::check_cdr('cdr duration: ',$cdr->{id},{ duration => '60.000' }); + my @split_cdrs = grep { !exists $cdr_id_map{$_->{id}}; } @{ Utils::Rateomat::get_cdrs_by_call_id($cdr->{call_id}) }; + if ((scalar @split_cdrs) > 0) { + is(scalar @split_cdrs,1,'exactly one new split cdr'); + $cdr = $split_cdrs[0]; + Utils::Rateomat::check_cdr('split cdr is unrated: ',$cdr->{id},{ rating_status => 'unrated' }); + Utils::Rateomat::check_cdr('split cdr is fragmented: ',$cdr->{id},{ is_fragmented => '1' }); + Utils::Rateomat::check_cdr('split cdr duration: ',$cdr->{id},{ duration => ($call_minutes-$i)*60 . '.000' }); + $i++; + $onpeak = ($onpeak ? 0 : 1); + } else { + undef $cdr; + } + } + is(scalar keys %cdr_id_map,$call_minutes,"call was split into $call_minutes cdrs"); + my $duration_sum = 0; + my $caller_costs_sum = 0; + my $caller_provider_costs_sum = 0; + foreach my $cdr_id (keys %cdr_id_map) { + $cdr = $cdr_id_map{$cdr_id}; + $duration_sum += $cdr->{duration}; + $caller_costs_sum += $cdr->{source_customer_cost}; + $caller_provider_costs_sum += $cdr->{source_reseller_cost}; + } + ok($duration_sum == $call_minutes * 60,'sum of rated duration is ' . $call_minutes * 60 . ' secs'); + ok($caller_costs_sum == $caller_costs,'caller costs is ' . $caller_costs); + ok($caller_provider_costs_sum == $caller_provider_costs,'caller provider costs is ' . $caller_provider_costs); + +} + +#print $tb->stringify; + +done_testing(); +exit; + +sub create_provider { + my ($peaktime_special_date,$call_minutes) = @_; + my $start = Utils::Api::datetime_from_string($peaktime_special_date . ' 08:00:00'); + my @special_peaktimes = (); + foreach my $i (1..$call_minutes/2) { + ($start,my $special_peaktime) = get_interleaved_special_peaktimes($start); + push(@special_peaktimes,$special_peaktime); + } + my @peaktimes = ( + peaktime_weekdays => [ map { #offpeak times: + ({ weekday => $_, + stop => '07:59:59', + }, + { weekday => $_, + start => '16:59:59', + }); } (0..6) + ], + peaktime_special => \@special_peaktimes, + ); + return Utils::Api::setup_provider('test.com', + [ #rates: + { + @peaktimes, + fees => [ + { + direction => 'out', + destination => '.', + onpeak_init_rate => 30, + onpeak_init_interval => 60, + onpeak_follow_rate => 10, + onpeak_follow_interval => 60, + offpeak_init_rate => 3, + offpeak_init_interval => 60, + offpeak_follow_rate => 1, + offpeak_follow_interval => 60, + }, + ]}, + ], + [ #billing networks: + ], + #provider rate + { + @peaktimes, + fees => [ + { + direction => 'out', + destination => '.', + onpeak_init_rate => 40, + onpeak_init_interval => 60, + onpeak_follow_rate => 20, + onpeak_follow_interval => 60, + offpeak_init_rate => 4, + offpeak_init_interval => 60, + offpeak_follow_rate => 2, + offpeak_follow_interval => 60, + }, + ]} + ); +} + +sub get_interleaved_special_peaktimes { + my $start = shift; + $start->add(seconds => 60); + my $end = $start->clone->add(seconds => 59); + my $next_start = $end->clone->add(seconds => 1); + return ($next_start, + { start => Utils::Api::datetime_to_string($start), + stop => Utils::Api::datetime_to_string($end), + }); +}