Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Perl - подскажите, как модифицировать код / 2 сообщений из 2, страница 1 из 1
11.11.2014, 16:53
    #38802408
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Perl - подскажите, как модифицировать код
Есть биллинговая система на Perl.
В системе есть клиенты, у клиентов есть счета, у счетов есть услуги. У каждой услуги есть тарифный план, определяющий порядок списания абонентской платы и ее величину.
Периодически или по событию осуществляется списание абонентской платы за подключенные услуги со счета.
Если средств на счету достаточно — услуги подключаются (или остаются подключенными). Если средств на счету нет — услуги отключаются (или остаются отключенными).
Но если на счету средства есть, но не на все услуги, то часть услуг подключается, часть услуг остается отключенной. Причем какого-нибудь документированного регламента по приоритету услуг нет, поэтому нельзя запланировать, какие услуги подключаться, а какие отключаться.
Я хочу изменить это поведение, сделать так, чтобы все услуги подключались или отключались только пачкой — если средств на счету хватает на все, то все подключить, если не хватает на все, то все отключить.
Но код системы довольно запутанный, а я не так хорошо знаю Perl. Во всяком случае несколько package в одном pm-файле и $class->SUPER мне незнакомы.

Обработкой абонплаты занимается скрипт со следующим кодом:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
...
use BL::AbonFee;
...
sub process_services {
...
    foreach (@$services) {
        $dbh->begin_work;
        $logger->writeLog(0, "[$$] start service ".(++$scounter)." (id $_)");
        try {
            if ($process_type eq 'postpaid') {
                $fee->process_postpaid(service_id => $_);   
            }
            else {
                $fee->process(service_id => $_);
            }
        } catch BL::AbonFee::Exception::Nomoney with {
            $logger->writeLog(LOG_INFO, "[$$] no money for service $_");
        };
        $dbh->commit;
        $logger->writeLog(LOG_INFO, "[$$] stop service $_");
    }
...
}
...
my @sths;
push @sths, [$dbh->prepare(qq{
    SELECT service_id
    FROM services
    WHERE ((status > 0) OR (status=$bm_status_service{off_freezed}))
      AND reckoning_date IS NOT NULL AND reckoning_date <= NOW()
    ORDER BY $order}
), 'common'];
foreach my $step (@sths) {
    my ($sth, $type) = @$step;
    
    $sth->execute;
    
    my @services;
    while (my $r = $sth->fetchrow_arrayref) {
        push @services, $$r[0];
        next if scalar(@services) < $chunk;
        process_services($fork, $logger, \@services, $type);
    }
    $sth->finish;
    process_services($fork, $logger, \@services, $type) if scalar @services;
    
    $fork->wait_all;
}



Класс BL::AbonFee довольно большой (35 КБ), вот основные места:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
package BL::AbonFee;

use base qw(Class::Accessor::Fast);
...
sub new {
    my $class   = shift;
    my (%param) = @_;

    my $self = $class->SUPER::new({@_});
    
    $self->{logger} ||= $self->_init_logger;
    
    # fetch dict     
    tie my %tie, 'BM::DBHash::Scalar', $self->dbh, 'dict', 'dict_id', 'attribute', { bm_class => ['tariffel', 'sm'] };
    my %dict = %tie;
    untie %tie;
    
    $self->dict({%dict});
    
    my %lists = (
        periodic_types        => [qw(bm_periodic_type  periodic_type_id  mnemonic)],
        charge_types          => [qw(bm_charge_type  mnemonic  charge_type_id)],
        service_status        => [qw(bm_status_service  mnemonic status_id)],
        actual_service_status => [qw(bm_actual_status_service  mnemonic  status_id)],
        service_types         => [qw(bm_type type_id mnemonic)],
        #tariffel_types        => [qw(bm_tariffel_type  mnemonic  tariffel_type_id)]
    );
    
    $self->_hash_list($_, @{$lists{$_}}) foreach keys %lists;
    
    foreach (values %{$self->periodic_types}) {
        my $class = 'BL/AbonFee/' . $_ . '.pm';
        eval {
            require $class;
        };
        die "no module defined for periodic type '$_': $@" if $@;
    }
    
    $self->{partner_prc} = BL::Partner->new($self->dbh);
    $self->{periodic_acct} = BL::PeriodicAcct->new(dbh => $self->dbh, logger => $self->logger);
    $self->{counter_prc} = BL::Counter->new($self->dbh);
    
    $self->{radappsrv} = try {
        my $srv = BM::RadiusAppServer->connect($self->dbh);
        $srv->auth;
        return $srv;
    } catch BM::RadiusAppServerException with {};
    
    return $self;
}
sub process {
    my $self = shift;
    $self->prepare_charges(1, @_);
}
...
1;

#

package BL::AbonFee::base;

use base qw(Class::Accessor::Fast);
...
package BL::AbonFee::Exception;
use base 'BM::Exception';

package BL::AbonFee::Exception::Nomoney;
use base 'BL::AbonFee::Exception';

1;



За списания отвечает, насколько я смог разобраться, этот фрагмент:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
        my $money = $fee->prepare;
        $self->logger->writeLog(LOG_INFO, "[$$] money: $money");
        
        my $ignored_money = 0;
        
        if ($flag && !$is_xc) {
            try {
                $ignored_money += $fee->create;
            } catch BL::AbonFee::Exception::Nomoney with {
                $is_xc = 1;
                $self->logger->writeLog(LOG_DEBUG, "[$$] not enough money but continue for counting total sum");
            };
        }



$fee в свою очередь это экземпляр класса BL::AbonFee::prepaid:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
sub create {
    my $self = shift;

    return 0 unless ($self->check_balance());
    my $ignored_money;

    if ($self->service_immortal || ($self->avail_money >= $self->{money}) || ($self->tariffel_type($self->periodic_acct->tariffel_id()) eq 'off_freezed_fee')) {
        $ignored_money = $self->SUPER::create;
        $self->update_account;
        #$self->update_service($self->cnt_period->next_period_stop_date($self->periodic_acct->period_start));
        $self->update_service($self->periodic_acct->period_stop);
    } else {
        $self->update_service;
        throw BL::AbonFee::Exception::Nomoney($self->{money});
    }
    
    return $ignored_money;
}



Если я правильно понял логику работы, мне нужно организовать дополнительную проверку в самом первом скрипте, просуммировав абонплату на всех услугах для одного счета и перенеся логику из класса BL::AbonFee в вышестоящий скрипт.

________________________
Мы смотрим с оптимизмом...
...в оптический прицел.
...
Рейтинг: 0 / 0
13.11.2014, 00:36
    #38804167
Warstone
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Perl - подскажите, как модифицировать код
Вам в ветку работа. С точки зрения СУБД - надо begin_work и commit 1) Вывести за цикл. 2) По ексепшену - откатывать транзакцию.

А вообще при изменении $order в запросе вы можете поменять порядок подключения / отключения сервисов.

ЗЫ: Код древний... Тут нету Class::XSAccessor'а минимум.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Perl - подскажите, как модифицировать код / 2 сообщений из 2, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]