You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ngcp-api-tools/bin/ngcp-fraud-daily-lock

147 lines
5.0 KiB

#!/usr/bin/perl
use strict;
use warnings;
use Email::Sender::Simple qw(sendmail);
use Sipwise::Provisioning::Billing;
my %LOCK = (
none => undef,
foreign => 1,
outgoing => 2,
incoming => 3,
global => 4,
0 => 'none',
1 => 'foreign',
2 => 'outgoing',
3 => 'incoming',
4 => 'global',
);
my $conf = Sipwise::Provisioning::Config->new()->get_config();
my $o = Sipwise::Provisioning::Billing->new();
my $db = $o->{database};
my $a = $db->sql_get_all_arrayref(<<"!");
SELECT bpinfo.type, bpinfo.id,
IF (bpinfo.fraud_use_reseller_rates > 0, SUM(cdr.source_reseller_cost),
SUM(cdr.source_customer_cost)) as daily_cost,
bpinfo.fraud_daily_limit, bpinfo.fraud_daily_lock, bpinfo.fraud_daily_notify
FROM (
SELECT contracts.id, bp.fraud_use_reseller_rates,
CASE WHEN cfp.fraud_daily_limit > 0 THEN 'account_limit'
ELSE 'profile_limit' END as type,
IF (cfp.fraud_daily_limit > 0, cfp.fraud_daily_limit, bp.fraud_daily_limit) as fraud_daily_limit,
IF (cfp.fraud_daily_limit > 0, cfp.fraud_daily_lock, bp.fraud_daily_lock) as fraud_daily_lock,
IF (cfp.fraud_daily_limit > 0, cfp.fraud_daily_notify, bp.fraud_daily_notify) as fraud_daily_notify
FROM billing.contracts
JOIN billing.billing_profiles bp
ON (bp.id =
(SELECT m.billing_profile_id
FROM billing.billing_mappings m
USE INDEX (contractid_idx)
WHERE ((m.start_date IS NULL) OR (m.start_date <= NOW()))
AND ((m.end_date IS NULL) OR (m.end_date >= NOW()))
AND (m.contract_id = contracts.id)
ORDER BY m.start_date DESC LIMIT 1
)
)
LEFT JOIN billing.contract_fraud_preferences cfp ON cfp.contract_id = contracts.id
WHERE (contracts.status = 'active')
AND (cfp.fraud_daily_limit > 0 OR bp.fraud_daily_limit > 0)
) as bpinfo
JOIN accounting.cdr ON cdr.source_account_id = bpinfo.id
WHERE cdr.start_time BETWEEN UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d 00:00:00'))
AND UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d 23:59:59'))
GROUP BY bpinfo.id
HAVING daily_cost >= fraud_daily_limit
!
my $x = {};
for my $e (@{ $a }) {
if(exists $x->{$e->{id}}) {
if($x->{$e->{id}}->{type} eq 'profile_limit' && $e->{type} eq 'account_limit') {
# if account limit hits and it has lock and/or notify, mark for action
if(defined $e->{fraud_daily_limit} and
int($e->{daily_cost}) >= int($e->{fraud_daily_limit}) and
($e->{fraud_daily_lock} || $e->{fraud_daily_notify})) {
$x->{$e->{id}} = $e;
} else {
# we have account fraud prefs set, but either the limit is not reached
# or no actions are necessary, let it slip through, overriding
# billing profile fraud settings
delete $x->{$e->{id}};
}
}
} else {
# if account or billing profile limit hits and it has lock and/or notify,
# mark for action
if(defined $e->{fraud_daily_limit} and
int($e->{daily_cost}) >= int($e->{fraud_daily_limit}) and
($e->{fraud_daily_lock} || $e->{fraud_daily_notify})) {
$x->{$e->{id}} = $e;
}
}
}
for my $e (values %{ $x }) {
$e->{fraud_daily_lock} and
$o->lock_voip_account({id => $e->{id}, lock => $LOCK{$e->{fraud_daily_lock}}});
$e->{fraud_daily_notify} or next;
my $subs = $db->sql_get_all_arrayref(<<"!", $e->{id});
SELECT s.username, d.domain, s.external_id
FROM voip_subscribers s
LEFT JOIN domains d ON d.id = s.domain_id
WHERE s.contract_id = ?
AND s.status != 'terminated'
!
my $cur = sprintf('%.2f', $e->{daily_cost} / 100);
my $max = sprintf('%.2f', $e->{fraud_daily_limit} / 100);
my ($subject, $body);
if ($e->{fraud_daily_lock}) {
$body = "Account ID " . $e->{id} . " has been locked due to exceeding the configured" . "\n"
. "daily credit balance threshold ($cur >= $max ) in the "
. ($e->{type} eq 'profile_limit' ? 'billing profile' : 'account settings') . "\n\n";
$subject = 'Account ID ' . $e->{id} . ' locked by daily fraud detection';
}
else {
$body = "Account ID " . $e->{id} . " is currently exceeding the configured daily credit balance" . "\n"
. "threshold ($cur >= $max) in the "
. ($e->{type} eq 'profile_limit' ? 'billing profile' : 'account settings') . ",\n"
. "but has not been locked due to configuration.\n\n";
$subject = 'Account ID ' . $e->{id} . ' exceeding daily fraud detection limit';
}
if (!$subs || !@$subs) {
$body .= "There are no affected subscribers.\n";
}
else {
$body .= "Affected subscribers:\n";
for my $s (@$subs) {
$body .= "\t$s->{username}\@$s->{domain}".
($s->{external_id} ? " (external ID '$s->{external_id}')"
: '') . "\n";
}
}
sendmail ( Email::Simple->create(
header => [
To => $e->{fraud_daily_notify},
From => $$conf{adminmail},
Subject => $subject,
],
body => $body,
));
}
1;